#1:变量可以在3个不同的地方分配,分别对应着3种不同的作用域:
#A:如果变量在def内赋值,它被定位在这个函数之内
#B:如果一个变量在一个嵌套的def中赋值,对于嵌套的函数来说,它是非本地的
#C:如果在def之外赋值,它就是全局的
#D:python中的变量查找顺序是:本地作用域->上一层def或lambda的本地作用域->全局作用域->内置作用域
#2.
#内置作用域通过一个名为__builtin__的标准库模块实现,前一半是内置的异常,后一半是内置函数
import builtins
str = dir(builtins)
#str = ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError',...
#3.
#A:global是一个命名空间声明,告诉python生成一个全局变量名,一般来说慎用global
#B:可以通过import来导入另一个文件的全局变量,但是最好别去修改,在文件间通信的最好方法是通过调用函数,传递参数然后获得返回值
y = 10
def Fun():
global X
global y
y = 20
X = 10
#global x = 10 #编译错误
Fun()
value = X #value = 10,若没有调用Fun()会导致运行错误
value1 = y #value1 = 20
#4.
def Fun0():
L0 = [1, 2, 3]
def Fun1(): #能记住嵌套作用域的变量的函数,尽管那个作用域可能已经不存在了
L0.append('a')
return L0
return Fun1
value = Fun0() #value = <function Fun0.<locals>.Fun1 at 0x000000000273F950>
value1 = value() #value1 = [1, 2, 3, 'a']
#5.
#A:在某一个函数内部调用一个之后才被定义的函数是可行的,只要第二个函数定义的运行实在第一个函数调用前就行,在def内部的代码直到这个函数运行时才被验证
def FunA():
return FunB() #若在调用FunA()时候,FunB没有被定义则运行出错
def FunB():
return 'B'
value = FunA() #value = 'B'
#6.
#A:lambda 表达式:由于嵌套作用域查找,lambda能够使用在上层函数作用域中的所有可用变量
def FunT():
value = 10
action = lambda n: value ** n
return action
value = FunT()(2) #value = 100
#7.
#A:如果lambda或者def在函数中定义,嵌套在一个循环之中,并且嵌套的函数引用了一个上层作用域的变量,该变量被循环所改变,所有在这个循环中产生的函数将会有相同的值,即最后一次循环中完成时候被引用变量的值
#B:因为嵌套作用域中的变量在嵌套函数被调用时候才进行查找,所以他们实际上记住的是同一个值,为了让如下的代码能正常进行工作,必须使用默认参数把当前值传递给嵌套作用域的变量,因为默认参数是在嵌套函数创建时候评估而非调用时候评估
def FunA():
L0 = []
for i in range(1, 3):
L0.append(lambda : i ** 2)
return L0
value = FunA() #value = [<function FunA.<loca...00290F9D8>, <function FunA.<loca...00290FB70>]
v0 = value[0]() #v0 = 4
v1 = value[1]() #v1 = 4
def FunA():
L0 = []
for i in range(1, 3):
L0.append(lambda : i ** 2)
i = 10
return L0
value0 = FunA()[0]() #value0 = 100
value1 = FunA()[1]() #value1 = 100
def FunA():
L0 = []
for i in range(1, 3):
L0.append(lambda i = i: i ** 2)
i = 10
return L0
value0 = FunA()[0]() #value0 = 1
value1 = FunA()[1]() #value1 = 4
#8.
#A:在函数中,可以引用外部作用域的变量,但是不能让这个变量去引用别的值,当使用了global时就可以达到这个目的
L0 = []
def Fun():
L1 = L0
L1.append(10)
L1 = 1
Fun() #L0 = [10]
def Fun():
global L0
L0.append(10)
L0 = 1
Fun() #L0 = 1
#9.
#默认情况下,不允许修改嵌套的def作用域中的名称,使用nonlocal可以达到这个目的
#nonlocal和global一样,声明了将要在一个嵌套的作用域中修改的名称,和global不同的是,nonlocal应用于一个嵌套的函数作用域中的名称而不是所有def之外的全局模块作用域
#而且在声明nonlocal的时候,他必须已经存在于该嵌套函数的外部函数的作用域中,nonlocal实现了把一个名称的查找限制在嵌套的def中
#global声明变量的时候,变量可以不存在,但是在后续的使用时,必须先定义该变量
def Fun():
value = 0
def FunA():
try:
value += 1
except:
pass #调用FunA的时候会运行至此
return FunA
F0 = Fun()
F0()
def Fun():
value = 0
def FunA():
nonlocal value
value += 1
return value
return FunA
F0 = Fun()
value = F0() #value = 1
value = F0() #value = 2
F1 = Fun()
value = F1() #value = 1
F0 = None
F0 = Fun()
value = F0() #value = 1
value = F1() #value = 2
def Fun0():
value = 0
def FunA():
def FunB():
nonlocal value
value += 1
return value
return FunB
return FunA
value = Fun0()()() #value = 1
value = Fun0()()() #value = 1
pFun = Fun0()
value = pFun()() #value = 1
value = pFun()() #value = 2
def Fun1():
global Fun1Value #将Fun1Value加入到全局作用域中
Fun1Value = 10 #由于Fun1Value没有在Fun1外部定义,所以在使用Fun1Value前必须先进行定义,否则会发生错误
Fun1Value += 1
return Fun1Value
value = Fun1() #value = 11
value = Fun1Value #value = 11 Fun1Value = 11
def Fun2():
global Fun2Value
try:
Fun2Value += 1
except:
Fun2Value = 0
Fun2() #Fun2Value = 0
Fun2() #Fun2Value = 1
Fun2() #Fun2Value = 2