标签:作用域 09 空间 -- 名称 func print 全局 def
1.名称空间
名称空间(namespaces):存放名字的地方,是对栈区的划分。有了名称空间之后,就可以在栈区中存放相同的名字,不会冲突。
详细的名称空间:分为三种:
1.1 内置名称空间
# 存放的名字:存放的python解释器内置的名字
>>> print
<built-in function print>
>>> input
<built-in function input>
# 存活周期:python解释器启动则产生,python解释器关闭则销毁
1.2 全局名称空间
# 存放的名字:只要不是函数内定义(局部名称空间)、也不是内置的(内置名称空间),剩下的都是全局名称空间的名字。
# 存活周期:python文件执行则产生,python文件运行完毕后销毁
# 以下都是全局名称空间:
import os # os
x=10 # x
if 13 > 3: # y, z
y=20
if 3 == 3:
z=30
# func=函数的内存地址
def func(): # func
a=111
b=222
class Foo: # Foo
pass
1.3 局部名称空间
注意:局部名称空间,一定是函数调用时产生,定义函数时不会产生局部空间
# 存放的名字:在调用函数时,运行函数体代码过程中产生的函数内的名字
# 存活周期:在调用函数时存活,函数调用完毕后则销毁
def func(a,b):
pass
# 函数调用一次,都产生一个局部空间,下面是四个局部空间
func(10,1)
func(11,12)
func(13,14)
func(15,16)
1.4 名称空间的顺序
总结:定义阶段:就是申明各种名字,调用阶段:就是使用各种名字。
所以,调用时,查找名字的顺序,就是根据定义阶段产生的各种名字,一层一层的去找。
a.名称空间的加载顺序:
内置名称空间>全局名称空间>局部名称空间
b.销毁顺序:
局部名称空间>全局名空间>内置名称空间
c.名字的查找优先级:当前所在的位置向上一层一层查找:
内置名称空间
全局名称空间
局部名称空间
# 如果当前在局部名称空间:
局部名称空间—>全局名称空间->内置名称空间
input=333 # 全局input
def func():
input=444
print(input) # 局部input
func()
# 如果当前在全局名称空间
全局名称空间->内置名称空间
input=333
def func():
input=444
func()
print(input) # 全局input
# 示范1:查找顺序,不是单纯的在其之前的代码去寻找(是在其空间有就行)
def func():
print(x)
x=111
func() # 111
# 示范2:名称空间的"嵌套"关系是以函数定义阶段为准,与调用位置无关
无论函数在哪调用,都要回到定义函数阶段去看,变量引用在哪个名称空间
x=1 # 可以在这个位置
def func():
print(x) # 定义阶段:函数func内没有局部x,就只能全局去找。
x=1 # 可以在这个位置
def foo():
x=222
func()
x=1 # 可以在这个位置
foo() # 1
解析:x= 1 可以在调用函数前的任意全局位置,没有的话就会报错;
永远也不会打印 foo局部内的 x= 222。因为定义阶段时,函数func内没有局部x,就只能全局去找。
# 示范3:函数嵌套定义
input=111
def f1():
def f2():
input=333
print(input)
input=222
f2()
f1() # 333-->222-->111-->内置
# 示范4:
x=111
def func():
print(x)
x=222
func()
# 报错,UnboundLocalError:
local variable 'x' referenced before assignment。绑定错误,说x=222,应当在print(x)之前
注意!!!
# 示例一:
x = 1
def func1():
print(x)
x = 3
func1() # 3
# 示例二:
y = 1
def func2(m=y):
print(m)
y = 3
func2() # 1
# 分析:为什么两个示例,结果不一样,有啥区别?
:示例一中,func1 定义阶段时,只是申明了func1 的名称空间;
函数体内的print(X) 是在func1调用阶段时执行,在其名称空间一层层寻找。
此时,名称空间里的x 是绑定3 的内存地址,故结果为3。
(只是可以这样理解,但实际是函数被调用时,才会产生局部名称空间)
:示例二中,func2 定义阶段时,申明了func2 和 其参数 m 的名称空间,
并且 参数m 已经绑定y的内存地址(此时,y是1的内存地址);
而函数体内的print(m) 是在func2调用阶段时执行,此时 m 仍为 1 的内存地址,故结果为1。
后续的 y = 3,就根本m 没有任何关系,因为在func2 定义阶段时,就已经将 m 绑定为 1 的内存地址了。
:实际上的原因是:默认参数的值是在函数定义阶段被赋值的,准确地说被赋予的是值的内存地址
2.作用域--->作用范围
# a.全局作用域:内置名称空间、全局名称空间
1.全局存活
2.全局有效:被所有函数共享
x=111
def foo():
print(x,id(x))
def bar():
print(x,id(x))
foo()
bar()
print(x,id(x))
# b.局部作用域: 局部名称空间的名字
1。临时存活
2。局部有效:函数内有效
def foo(x):
def f1():
def f2():
print(x)
# LEGB
# builtin
# global
def f1():
# enclosing
def f2():
# enclosing
def f3():
# local
pass
global 与 nonlocal
########### global
# 示范1:
x=111
def func():
x=222
func()
print(x) # 111
# 示范2:如果在局部想要修改全局的名字对应的值(不可变类型),需要用global
x=111
def func():
global x # 声明x这个名字是全局的名字,不要再造新的名字了
x=222
func()
print(x) # 222
# 示范3:若是在局部修改全局的可变类型值,不用使用global
l=[111,222]
def func():
l.append(333)
func()
print(l) # [111, 222, 333]
############ nonlocal:
从函数外层函数中一层一层去找,局部内的(不会找到全局去)
# nonlocal: 修改函数外层函数包含的名字对应的值(不可变类型)
x=0
def f1():
x=11
def f2():
nonlocal x
x=22
f2()
print('f1内的x:',x)
f1() # f1内的x:22
def f1():
x=[]
def f2():
x.append(1111)
f2()
print('f1内的x:',x)
f1() # [1111]
标签:作用域,09,空间,--,名称,func,print,全局,def 来源: https://www.cnblogs.com/Edmondhui/p/16367558.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。