Python——第四章:作用域
作用域: 变量的访问权限
-
全局变量 -> 全局作用域
-
局部变量 -> 局部作用域(比如在函数内定义的变量,只能在函数内调用)
a = 10 # 全局变量 -> 全局作用域 print(a) def func(): # 全局的一个函数 b = 20 # 局部变量, 局部作用域 print(a) # func() # print(b) def func3(): func() func3()
- 如果想要在函数外面访问到函数内部的东西. 必须要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 inner
和return 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
。在这里,a
是 func
函数的局部变量,但由于 inner
函数引用了它,a
的值在 inner
函数被调用时仍然是可用的。
这段代码可以实现的特殊效果:
1、因为迟迟没有使用ret()
调用ret
(inner
函数),程序为了能够持续提供可用性,会将该段代码常驻于内存。不会被内存回收。
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不论写在哪里都是全局作用于的变量内容
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)