Python——第四章:作用域

作用域: 变量的访问权限

  1. 全局变量 -> 全局作用域

  2. 局部变量 -> 局部作用域(比如在函数内定义的变量,只能在函数内调用)

    a = 10  # 全局变量 -> 全局作用域
    print(a)
    
    def func():   # 全局的一个函数
        b = 20   # 局部变量, 局部作用域
        print(a)
    
    # func()
    # print(b)
    
    def func3():
        func()
    func3()
  3. 如果想要在函数外面访问到函数内部的东西. 必须要return
    def func():
        c = 10086
        return c  # 如果想要在函数外面访问到函数内部的东西. 必须要return
    
    c1 = func()
    print(c1)

总结: 里面访问外面没问题, 外面访问里面不能直接访问到

 

函数可以嵌套函数

综上:
    1, 函数可以作为返回值进行返回
    2, 函数可以作为参数进行互相传递
    函数名实际上就是一个变量名, 都表示一个内存地址

函数嵌套举例:

def func1():
    b = 20
    def func2():  # 函数的嵌套, 局部变量
        pass
    # func2 = def():
    print(b)
    func2()  # 局部的东西. 一般都是在局部自己访问使用的


print(func1())

函数相互调用举例:

def func1():
    pass

def func2():
    func1()  # 这个叫函数间的调用. 不叫嵌套

func2()

函数互相嵌套的运行顺序

def func1():    # 2
    print(123)    # 3
    def func2():  # 6  
        print(456)    # 7
        def func3():    # 10
            print(789)    # 11
        print(1)    # 8
        func3()    # 9
        print(2)    # 12
    print(3)    # 4
    func2()    # 5
    print(4)    # 13

func1()    # 1 执行从这里开始

#运行结果
123
3
456
1
789
2
4

局部变量函数,要在外部使用

def func():
    def inner():
        print(123)
    print(inner)
    return inner  # 返回的是一个函数, 此时我们把一个函数当成一个变量进行返回的

b1 = func()  # b1是func的内部inner
print(b1)
b1()

def an():
    print(123)
an()
bn = an
bn()

return innerreturn inner()是不一样的

 

函数的实参可以是:变量

def func(an):
    print("实参调用变量c")

c = 123
func(c)

 

函数的实参可以是:函数

def func(an):    # 此时an收到的是一个函数
    print(an)    # 注意这里不是an()

def target():
    print("实参调用的是函数")

func(target)    # 实参是个函数

#执行结果
<function target at 0x000001F0E09116C0>

代理模式执行函数,func()本身不执行实际内部target()函数

def func(an):  # 此时an收到的是一个函数
    an()    # 执行这个函数

def target():
    print("我是target")


func(target)

 

Global和nonlocal

global : 在局部,指定某些全局变量引入进来

nonlocal: 在局部,引入外层的局部变量,但不能引用到全局

这样运行程序,在函数func()内部无法修改成功全局变量a的值

a = 10    # 全局变量a
def func():
    a = 20  # 创建一个局部变量. 并没有去改变全局变量中的a

func()
print(a)

#运行结果:
10

如果此时我就想在函数内部修改全局的变量a,需要使用global

global : 在局部. 把某些全局变量引入进来

a = 10    # 全局变量a
def func():
    global a  # 把外面的全局变量引入到局部
    a = 20  # 此时全局变量a被函数内引用,并被正确修改。
func()
print(a)    # 结果为20

nonlocal: 在局部, 递进地引入外层的局部变量,但不能引用到全局

def func():
    a = 10
    def func2():
        nonlocal a  # 向外找一层. 看看有没有该变量. 如果有就引入, 如果没有, 继续向外一层, 但不能到全局
        a = 20
    func2()
    print(a)

func()

闭包:

本质, 内层函数对外层函数的局部变量的使用. 此时内层函数被称为闭包函数
    1. 可以让一个变量常驻与内存,可随时被外层函数调用。
    2. 可以避免全局变量被修改、被污染、更安全。(通过版本控制工具,将不同人所写的代码都整合的时候,避免出现问题)

def func():
    a = 10
    def inner():
        print(a)
        return a
    return inner

ret = func()

代码定义了一个函数 func,它返回了另一个函数 inner。这种结构被称为闭包(closure),因为 inner 函数引用了在其外部定义的变量 a。在这里,afunc 函数的局部变量,但由于 inner 函数引用了它,a 的值在 inner 函数被调用时仍然是可用的。

这段代码可以实现的特殊效果:

1、因为迟迟没有使用ret()调用retinner函数),程序为了能够持续提供可用性,会将该段代码常驻于内存。不会被内存回收。

2、用函数来定义局部变量a,并且局部变量不会被后续函数外的代码操控、改变,仅可以被赋值后读取、打印。不能被其他全局变量修改。实现局部变量仅可以在本函数内部才可以被操作。a被保护起来了。

3、想调用这个局部变量a,可以随时调用ret()函数,使得局部变量既可以被调用,还不会被修改。

 

未来某一时刻,ret()调用了 func 函数并将其结果赋值给变量 ret。此时,ret 包含了 inner 函数。如果你调用 ret(),它将输出 10,因为 inner 函数引用了外部的 a 变量,而 a 的值在 func 函数被调用时被设置为 10

 

再看下面一段代码

def func():
    a = 0
    def inner():
        nonlocal a
        a += 1
        return a
    return inner


ret = func()
a = 20    #此时即使出现了全局变量a=20,也不会干扰到func函数局部变量a的计数器累计
# inner => ret => 什么时候执行
r1 = ret()
print(r1)    #第一次输出,结果为1

# 可能1000000行后才执行

r2 = ret()
print(r2)    #第二次输出,结果为2

print(ret())    #结果为3
print(ret())    #结果为4

这段代码,常驻于内存,有实现内部计数器的作用。

 

locals和globals

locals:函数会以字典的类型返回当前位置的所有局部变量:

globals:函数会以字典的类型返回全部局部变量:

 

locals:

下面这段代码:此时locals被写在了全局作用域范围内. 此时看到的就是当前作用域(全局)中的变量内容

a = 188

print(locals())  # 此时locals被写在了全局作用域范围内. 此时看到的就是当前作用域(全局)中的内容

#执行结果
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000166DC5150D0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\Python\\装饰器.py', '__cached__': None, 'a': 188}

下面这段代码:此时locals放在局部作用域范围, 看到的就是局部作用域的变量内容

a = 188

def func():
    b = 336
    print(locals())  # 此时locals放在局部作用域范围, 看到的就是局部作用域的内容
func()

#运行结果
{'b': 336}

globals

此时globcals虽然放在局部作用域范围, 但是看到的是全局作用域的变量内容

a=188

def func():
    b = 336
    print(globals())  # 此时globals虽然放在局部作用域范围, 但是看到的是全局作用域的内容
func()

#运行结果
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000166DC5150D0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\Python\\装饰器.py', '__cached__': None, 'a': 188, 'func': <function func at 0x00000166DC7EA020>}

globcals不论写在哪里都是全局作用于的变量内容

posted @ 2023-11-30 00:34  Magiclala  阅读(11)  评论(0编辑  收藏  举报