基础篇_010_函数_作用域

  "作用域"是紧跟着嵌套函数("基础篇_010_函数_全局变量与局部变量")来讲的,在"全局变量与局部变量"中我们依靠的就是函数的嵌套,这也就牵扯出了一个问题——变量的作用域(这仅仅是同名变量的时候才有此类问题),即这个变量名到底是代指的哪一个值?

 

----前奏(函数名是个什么东西) ===》

  在问题的开始,必须让大家真正认识到函数名是个什么东西。函数名:整个函数的代称,存储的是函数的地址,加上()便可调用函数 ↓

# 1. 函数名是函数的地址
def foo():
    pass
print(foo)      # 输出函数名:<function foo at 0x000002B1B71A86A8>
print(foo())    # 输出函数的返回值:None

# 2. 函数的返回值为函数名,尝试调用返回值
def foo1():
    print("from foo1()")
    return foo2
def foo2():
    print("from foo2()")
    return
result = foo1()  # 只是调用foo1()函数,输出 from foo1()
# foo1()的返回值为 foo2,而foo2是foo2()函数的地址 ===》result就是foo2()函数的地址
# 得到了函数的地址,那么加上()便可以运行函数
result()    # 执行foo2()函数,输出 from foo2()

 

----问题的引入(思考一下为什么) ===》

# 1. 当内部函数中已经定义了一个同名的变量
name = "simba"
def foo():
    name = "wang"
    def bar():
        name = "wupeiqi"
        print(name)
    return bar
foo()() # 输出:wupeiqi

  这个很好理解,因为在自己家(bar()函数内部就已经定义了一个name),直接拿来用就行了,不用去外面找。

  那我们再来看下一段代码(错误思考方式:仅仅考虑到函数在编译时是以字符串的方式存在内存中的) ===》

# 2. 当内部函数中没有定义同名变量
name = "simba"
def foo():
    name = "wang"
    def bar():
        print(name)
    return bar
foo()() # 输出:wang

  卧槽,bar()函数不是在全局调用的嘛,怎么不是全局变量"simba",而是局部变量"wang"?

 

----问题的剖析 ===》

  虽然函数在编译时是以字符串的方式存在内存中的,但是于此同时Python还会将函数的嵌套格局(作用域关系)记录下来,由于这是在定义函数时就形成了的,所以无论函数的调用在哪,函数都将按照定义时的格局(作用域关系)来运行,故而上面的例子将会输出"wang"。

 

----加大力度 ===》

 1 # 加大力度
 2 name = "simba"
 3 def foo_out():
 4     name = "from foo_out()"
 5     def foo_middle():
 6         name = "from foo_middle()"
 7         def foo_in():
 8             print(name)
 9         # end foo_in()
10         return foo_in
11     # end foo_middle()
12     return foo_middle
13 # end foo_out()
14 
15 foo_out()()()
16 # 输出:from foo_middle()

  step1(第02行): name = "simba"

  step2(第15行): 执行foo_out(),后面两个()先不管

  step3(第04行): 创建foo_out()中的局部变量name = "from foo_out()"

  step4(第12行): 结束foo_out()函数,返回foo_middle()函数的地址

  step5(第15行): 执行(foo_out())(),其中foo_out()的结果就是foo_middle()函数的地址,即执行foo_middle()

  step6(第06行): 创建foo_middle()中的局部变量name = "from foo_middle()"

  step7(第10行): 结束foo_middle()函数,返回foo_in()函数的地址

  step8(第15行): 执行((foo_out())())(),其中(foo_out())()的结果就是foo_in()函数的地址,即执行foo_in()

  step9(第08行): 打印name,由于在定义函数时就已经创建出了作用域关系,所以此时的name为"from foo_middle()"

 

 

posted @ 2020-02-14 12:02  BNTU  阅读(85)  评论(0)    收藏  举报