作用域

在函数中,Python 从命名空间中寻找变量的顺序如下:

  • local function scope
  • enclosing scope
  • global scope
  • builtin scope 例子:

local 作用域

In [1]:

  1. def foo(a,b):
  2. c = 1
  3. d = a + b + c

这里所有的变量都在 local 作用域。

global 作用域

In [2]:

  1. c = 1
  2. def foo(a,b):
  3. d = a + b + c

这里的 c 就在 global 作用域。

global 关键词

使用 global 关键词可以在 local 作用域中修改 global 作用域的值。

In [3]:

  1. c = 1
  2. def foo():
  3. global c
  4. c = 2
  5.  
  6. print c
  7. foo()
  8. print c
  1. 1
  2. 2

其作用是将 c 指向 global 中的 c

如果不加关键词,那么 local 作用域的 c 不会影响 global 作用域中的值:

In [4]:

  1. c = 1
  2. def foo():
  3. c = 2
  4.  
  5. print c
  6. foo()
  7. print c
  1. 1
  2. 1

built-in 作用域

In [5]:

  1. def list_length(a):
  2. return len(a)
  3.  
  4. a = [1,2,3]
  5. print list_length(a)
  1. 3

这里函数 len 就是在 built-in 作用域中:

In [6]:

  1. import __builtin__
  2.  
  3. __builtin__.len

Out[6]:

  1. <function len>

class 中的作用域

Global MyClass
var = 0 MyClass access_class var = 1access_class

In [7]:

  1. # global
  2. var = 0
  3.  
  4. class MyClass(object):
  5. # class variable
  6. var = 1
  7.  
  8. def access_class_c(self):
  9. print 'class var:', self.var
  10.  
  11. def write_class_c(self):
  12. MyClass.var = 2
  13. print 'class var:', self.var
  14.  
  15. def access_global_c(self):
  16. print 'global var:', var
  17.  
  18. def write_instance_c(self):
  19. self.var = 3
  20. print 'instance var:', self.var
Global MyClass obj
var = 0 MyClass [access_class] obj var = 1access_class

In [8]:

  1. obj = MyClass()

查询 self.var 时,由于 obj 不存在 var,所以跳到 MyClass 中:

Global MyClass obj
var = 0 MyClass [access_class self] obj var = 1access_class

In [9]:

  1. obj.access_class_c()
  1. class var: 1

查询 var 直接跳到 global 作用域:

Global MyClass obj
var = 0 MyClass [access_class self] obj var = 1access_class

In [10]:

  1. obj.access_global_c()
  1. global var: 0

修改类中的 MyClass.var

Global MyClass obj
var = 0 MyClass [access_class self] obj var = 2access_class

In [11]:

  1. obj.write_class_c()
  1. class var: 2

修改实例中的 var 时,会直接在 obj 域中创建一个:

Global MyClass obj
var = 0 MyClass [access_class self] obj var = 2access_class var = 3

In [12]:

  1. obj.write_instance_c()
  1. instance var: 3

In [13]:

  1. MyClass.var

Out[13]:

  1. 2

MyClass 中的 var 并没有改变。

词法作用域

对于嵌套函数:

In [14]:

  1. def outer():
  2. a = 1
  3. def inner():
  4. print "a =", a
  5. inner()
  6.  
  7. outer()
  1. a = 1

如果里面的函数没有找到变量,那么会向外一层寻找变量,如果再找不到,则到 global 作用域。

返回的是函数的情况:

In [15]:

  1. def outer():
  2. a = 1
  3. def inner():
  4. return a
  5. return inner
  6.  
  7. func = outer()
  8.  
  9. print 'a (1):', func()
  1. a (1): 1

func() 函数中调用的 a 要从它定义的地方开始寻找,而不是在 func 所在的作用域寻找。

原文: https://nbviewer.jupyter.org/github/lijin-THU/notes-python/blob/master/05-advanced-python/05.15-scope.ipynb