Python的作用域和其他语言有所不同,他有几个小窍门来判断作用域。
1. Python里面没有块级别的作用域;只有函数级别的作用域。
比如说,下面这个例子,如果是Java或者其他语言,肯定报错name没有定义。Python里面因为不存在块级别的作用域,因此name直接就输出9了>>> for i in range(10):
name=i
print(name)
----------
9
2. 作用域链的顺序是从内往外找,直到找不到为止
例如>>> def f1():
name='a'
def f2():
name='b'
print(name)
f2()
print(name)
f1()
--------------
b
a
3. 函数没有执行之前,作用域已经确定了,作用域链也已经确定了。
例如 f0()执行之前,已经确定了name就是alex,因此不管他如何调用,输出总是alex>>> name='alex'
def f0():
print(name)
def f1():
name='bbb'
f0()
def f2():
name='eric'
f1()
f2()
-----------------
alex
下面看几个特殊的例子和语法
比如,我们可以通过下面的方式给列表赋值>>> li=[x+100 for x in range(10)]
print(li)
li=[x+100 for x in range(10) if x>6]
print(li)
------------
[100, 101, 102, 103, 104, 105, 106, 107, 108, 109]
[107, 108, 109]
如果把上面的例子改成lambda表达式,那么因为lambda其实就是函数,他在未执行前是不会执行内部代码的,因此列表里面的每个元素都是函数,当我们()来执行的时候,他会尝试返回X,而X这个时候在10次循环之后已经是9了>>> #li列表里面的元素[函数,函数,函数],函数在没有执行前,内部代码不执行
li=[lambda :x for x in range(10)]
print(li)
print(li[0]())
-----------------
[. at 0x0000019EA4515BF8>, . at 0x0000019EA4515C80>, . at 0x0000019EA4515D08>, . at 0x0000019EA4515D90>, . at 0x0000019EA4515E18>, . at 0x0000019EA4515EA0>, . at 0x0000019EA4515F28>, . at 0x0000019EA452B048>, . at 0x0000019EA452B0D0>, . at 0x0000019EA452B158>]
9
换一种容易理解的写法。
>> li=[]
for i in range(10):
def f1():
return i
li.append(f1)
#li是列表,内部元素是相同功能的函数
#i=9
print(i)
## f1 没有调用之前,内部代码不执行;因此li内部都是函数
##真正执行() 时候,他会返回i,内部没有i,往上找,i已经是9了,因此返回9
print(li[0]())
print(li[2]())
9
9
如果改成x=i,f1初始化的时候会指定x的值>>> li=[]
for i in range(10):
def f1(x=i):
return x
li.append(f1)
#li是列表,内部元素是相同功能的函数
#i
print(i)
## f1 没有调用之前,内部代码不执行;因此li内部都是函数
##真正执行() 时候,他会返回i,内部没有i,往上找,i已经是9了,因此返回9
print(li[0]())
print(li[2]())
9
0
2