Python学习:作用域(namespace)

Python作用域基础

Python有四个作用域:

  1. L(Local)本地也称作局部作用域;
  2. E(Enclosing)闭包函数外的函数中;
  3. G(global)全局作用域;
  4. B(Built-in)内建作用域;

变量可以在三个不同的地方分配:

  • 如果一个变量在def内赋值,它被定位在这个函数之内。
  • 如果一个变量在嵌套的def中赋值,对于嵌套的函数来说,它是非本地的。
  • 如果在def之外赋值,它就是整个文件全局的。

值得注意的是,修改一个对象并不是对一个名称赋值。

变量名解析:LEGB原则

对于一个def语句:

变量名引用分为三个作用域进行查找:首先是本地,之后是函数内(如果有的话),之后全局,最后是内置。L->E->G->B

Python除了def/class/lambda外,其他如:if/elif/else/  try/except  for/while并不能改变作用域。定义在他们之内的变量,外部还是可以访问。

>>> if True:
...     a = ‘I am A‘
... 
>>> a
‘I am A‘
# 定义在if语言中的变量a,外部还是可以访问的。
# 但是需要注意如果if被 def/class/lambda 包裹,在内部赋值,就变成了此 函数/类/lambda 的局部作用

在def/class/lambda内进行赋值,就变成了其局部作用域。局部作用域会覆盖全局作用域,但不会影响全局作用域。

g=1            #全局变量
def func():
    g = 2      #局部变量
    return g

print func()    #结果为2
print g         #结果为1

值得注意的是,有时候想再函数内调用全局变量,疏忽了会报错,如下:

#file1
var = 1
def func():
    print var
    var = 200

func()

#file2
var = 1
def func():
    var = var +1
    return var

func()

#这两个函数都会报错UnboundLocalError: local variable ‘var‘ referenced before assignment

上述两个函数都会报同样的错误:为赋值之前引用变量!为什么?在函数内部,解释器探测到变量var重新被赋值,所以var变成了局部变量,但是在被赋值之前就使用了var,便会出现这个错误。解决的方法是在函数内部添加globals var语句,但运行函数后全局的var也会被修改。

#file1
var = 1
def func():
    global var
    print var
    var = 200

func()        #结果为1
print var     #全局变量var变为200

#file2
var = 1
def func():
    global var
    var = var +1
    return var

print func()        #结果为2

闭包Closure

闭包的定义:如果在一个内部函数里,对外部函数内(不是全局变量)进行引用,那么内部函数就被认为是闭包(closure)。

a = 1
def external():
    global a
    a = 200
    print a
    b =100
    def internal():
        print b
        b = 200
        return b
    internal()
    print b

print external()
#一样会报错,赋值前引用UnboundLocalError: local variable ‘b‘ referenced before assignment

Python3中有关键字nonlocal可以解决这个问题,但在Python2中尽量不要尝试修改闭包中的变量。

关于闭包,还有一个坑:

from functools import wraps

def wrapper(log):
    def external(F):
        @wraps(F)
        def internal(**kw):
            if False:
                log = ‘modified‘
            print log
        return internal
    return external

@wrapper(‘first‘)
def abc():
    pass

print abc()

也会出现 引用在赋值之前 的错误,原因是解释器探测到了 if False 中的重新赋值,所以不会去闭包的外部函数(Enclosing)中找变量,但 if Flase 不成立没有执行,所以便会出现此错误。除非你还需要else: log=‘var‘ 或者 if True 但这样添加逻辑语句就没了意义,所以尽量不要修改闭包中的变量。

好像用闭包无法实现计数器功能,因为在闭包内部count+=1就会出现在赋值前引用的错误(Python3用关键字nonlocal可以解决)

def counter(start):
    count = [start]
    def internal():
        count[0] += 1
        return count[0]
    return internal

count = counter(0)
for n in range(10):
    print count()
#结果分别为1,2,3,4,5,6,7,8,9,10

count = counter(0)
print count()
#结果为1

global和globals()

global用来在函数内部声明全局变量,globals() 和 locals() 提供了基于字典的访问全局和局部变量的方式。

比如:如果函数1内需要定义一个局部变量,名字另一个函数2相同,但又要在函数1内引用这个函数2。

def var():
    pass

def f2():
    var = ‘Just a String‘
    f1 = globals()[‘var‘]
    print var
    return type(f1)

print f2()
# Just a String
# <type ‘function‘>
时间: 2024-10-09 16:03:50

Python学习:作用域(namespace)的相关文章

Python学习之变量的作用域

学习地址:http://www.jianshu.com/p/17a9d8584530 1.变量作用域LEGB 1.1变量的作用域 在Python程序中创建.改变.查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域.python的作用域是静态的,在源代码中变量名被赋值的位置决定了该变量能被访问的范围.即Python变量的作用域由变量所在源代码中的位置决定. 1.2高级语言对数据类型的使用过程 一般的高级语言在使用变量时,都会有下面4个过程.当然在不同的语言中也会有

Python 学习笔记 - 作用域小知识

Python的作用域和其他语言有所不同,他有几个小窍门来判断作用域. 1. Python里面没有块级别的作用域:只有函数级别的作用域. 比如说,下面这个例子,如果是Java或者其他语言,肯定报错name没有定义.Python里面因为不存在块级别的作用域,因此name直接就输出9了 >>> for i in range(10):     name=i print(name) ---------- 9 2. 作用域链的顺序是从内往外找,直到找不到为止 例如 >>> def 

python学习笔记之module &amp;&amp; package

个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, __init__.py可以有两种形式, 一种是直接import多个模块,例如 import fibo import abc 另外一种是 __all__ = ["A","B"] python学习笔记之module && package python的mo

详解Python的作用域和命名空间

最近在学习Python,不得不说,Python真的是一门很好用的语言.但是学习的过程中关于变量作用域(scope)的命名空间(namespace)的问题真的把我给搞懵了.在查阅了相关资料之后,觉得自己对Python的作用域和命名空间有了一定得了解.故写在这里,一方面加深自己的理解,另一方面分享知识. 一.本篇博客需要解决的问题. 1.什么是作用域和命名空间? 2.Python中作用域和命名空间的工作原理是什么? 3.我怎样在Python中声明一个全局变量(global variable),局部变

Python学习笔记--未经排版

Python 学习笔记 Python中如何做到Print() 不换行 答:Print("输出内容",end='不换行的分隔内容'),其中end=后面为2个单引号 注:在Python 2.x中,Print "输出内容", 即在输出内容后加一逗号 Python中 is 和 == 的区别 答:Python中的对象包含三要素:id.type.value 其中id用来唯一标识一个对象,type标识对象的类型,value是对象的值 is判断的是a对象是否就是b对象,是通过id来

OpenCV for Python 学习 (二 事件与回调函数)

今天主要看了OpenCV中的事件以及回调函数,这么说可能不准确,主要是下面这两个函数(OpenCV中还有很多这些函数,可以在 http://docs.opencv.org/trunk/modules/highgui/doc/user_interface.html 找到,就不一一列举了),然后自己做了一个简单的绘图程序 函数如下: cv2.setMouseCallback(windowName, onMouse[, param]) cv2.createTrackbar(trackbarName,

[Python学习] 专题一.函数的基础知识

        最近才开始学习Python语言,但就发现了它很多优势(如语言简洁.网络爬虫方面深有体会).我主要是通过<Python基础教程>和"51CTO学院 智普教育的python视频"学习,在看视频中老师讲述函数知识的时候觉得非常不错,所以就写了第一篇Python学习的文章分享给大家.主要内容:         1.Python安装与基本输入输出,print()函数和raw_input()函数简单用法. 2.我根据视频中学到的知识,讲解函数的基本知识: (1).系统提

Python学习的个人笔记(基础语法)

Python学习的个人笔记 题外话: 我是一个大二的计算机系的学生,这份python学习个人笔记是趁寒假这一周在慕课网,w3cschool,还有借鉴了一些博客,资料整理出来的,用于自己方便的时候查阅,一开始保存在word上,代码不是很好看,于是决定复制到博客里面,可能有复制过程中出错的,或者我本身在理解方面有出错的地方,希望能得到指正,谢谢  后续的内容我会继续学习…… python下载地址  www.python.org Python 分为2.7和3.3两个版本,3.3有些库不兼容,因此用2.

Python:Python学习总结

背景 PHP的$和->让人输入的手疼(PHP确实非常简洁和强大,适合WEB编程),Ruby的#.@.@@也好不到哪里(OO人员最该学习的一门语言). Python应该是写起来最舒服的动态语言了,一下是一些读书笔记,最后会介绍一下高级的用法:Mixin.Open Class.Meta Programming和AOP. 文中有些地方是用2.7开发的,如果您安装的是3.x,有几点需要注意: print "xxx" 要换成 print("xxx") __metacla

python学习笔记6-函数变量

python学习笔记6-函数变量 局部变量和全局变量 Python中的任何变量都有特定的作用域 在函数中定义的变量一般只能在该函数内部使用,这些只能在程序的特定部分使用得变量我们称为局部变量 在一个文件顶部定义的变量可以供文件中的任何函数调用,这些可以为整个程序所使用的变量我们称为全局变量 [[email protected] ~]# vim value.py #!/usr/bin/python x=100 def fun():     global x     x +=1     global