第十七章 作用域

#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

  

原文地址:https://www.cnblogs.com/szn409/p/6641700.html