名称空间
名称空间:存放变量名与值绑定关系的地方
名称空间的分类:
1.内置名称空间
所有的内置函数等存储的空间。如print(),len()等等
2.全局名称空间
py文件运行时代码从上之下依次执行,看到一个变量就会将这个变量与对应值的内存地址的关系存到名称空间里
x=10 # 全局名称空间
def f1(): # f1也是全局名称空间
pass
if 1 > 0:
z=3 # 全局名称空间
if 3 > 1:
m=111 # 全局名称空间
3.局部名称空间
在函数内定义的名字,调用函数则产生一个函数局部名称空间,该函数调用结束则立即销毁
def f1():
y=2 # y局部名称空间
'''
不同的名称空间内的名称不会相互冲突,即是它们采用相同的名称。这也正是名称空间的作用。
'''
加载顺序:内置名称空间---->全局名称空间---->(函数执行时)局部名称空间
取值(查找顺序)顺序:(函数执行时)局部名称空间—>全局名称空间---->内置名称空间
(1)先从局部命名空间中查找,如果能查找到,则停止搜索。 如果找不到就去全局命名空间中查找,如果找到则停止搜索。 如果
找不到就去内置命名空间中查找,如果查找到则返回内容。 如果查不到就报错。
(2)如果一开始就从全局命名空间中查找,就直接找全局命名空间中的内容, 如果找到则停止搜索,如果找不到,就向内置命名
空间中查找。 如果查找到则返回内容。如果查不到就报错。
(3)注意事项: 自己的变量名称不要和内置的变量名相同,否则不能使用内置命名空间中的函数功能。
例子:
def func():
a = 20
print(a)
func()
print(a) # NameError: name 'a' is not defined
名称空间的作用域:
1.内置名称空间:在python文件中任意位置都能被引用,全局有效。
2.全局名称空间:在python文件中任意位置都能被引用,全局有效。
3.局部名称空间:只在局部有效,如函数,类等
称空间的存活周期:
1.内置名称空间
python解释器运行 产生
python解释器关闭 销毁
2.全局名称空间
py文件开始运行 产生
py文件运行结束 销毁
3.局部名称空间
函数体代码开始运行 产生
函数体代码运行结束 销毁
global与nonlocal关键字
global关键词:在局部名称空间内修改全局不可变类型
修改全局的不可变类型:
name = '春游去动物园'
def func1():
global name
name='python'
print(name)
print('函数运行前',name)
func1()
print('函数运行后',name)
执行结果:
函数运行前 春游去动物园
python
函数运行后 python
修改全局的可变类型:
test_list = [1, 2, 3, 4]
def func2():
test_list.append(5)
print('函数运行前',test_list)
func2()
print('函数运行后',test_list)
执行结果:
函数运行前 [1, 2, 3, 4]
函数运行后 [1, 2, 3, 4, 5]
"""
如果想要在局部修改全局的不可变类型
需要提前加关键字global申明
如果想要在局部修改全局的可变类型
不需要加关键字global申明
"""
nonlocal关键词:
1.不能修改全局作用域。
2.在局部作用域中,对父级作用域(后者更外层的作用域非全局作用域)的变量进行引用和修改,并且引用的哪层从哪层及以下的变量全部发生改变。
def func1():
b = 6
def func2():
nonlocal b # 从这层起对b进行修改,上一层的b也变为了666
b = 666
print(b)
func2()
print(b)
func1()
执行结果:
666
666
'''
1.内层修改外层的 不可变类型 时 需要 使用关键字nonlocal
2.内层修改外层的 可变类型 时 不需要 使用关键字nonlocal
函数名
函数名是函数的名字,本质是变量(特殊的变量),函数名()表示执行此函数。
1.单独打印函数名返回函数的地址
def func1():
print('春游去动物园')
print(func1)
执行结果:
<function func1 at 0x010896A0>
2.函数名的赋值
def func2():
print('春游去动物园')
f=func2
print(f())
执行结果:
春游去动物园
None
3.函数名可以作为参数
def f1(x):
print('6666')
def f2():
print('春游去动物园')
f1(f2())
执行结果:
春游去动物园
6666
4.函数名可以作为容器类数据的元素
def f1():
print(11)
def f2():
print(22)
def f3():
print(33)
l1=[f1,f2,f3]
for i in l1:
i()
print(l1)
执行结果:
11
22
33
[<function f1 at 0x015196A0>, <function f2 at 0x01E62E80>, <function f3 at 0x01E62E38>]
5.函数名可以作为函数的返回值
def f1():
print('第一个函数')
return f2()
def f2():
print('第二个函数')
f1()
执行结果:
第一个函数
第二个函数
函数的嵌套
函数的嵌套:在函数里面还有函数。分为外函数和内函数。
嵌套函数是为函数内部服务的,比如减少代码的重复,想要调用函数,要使用函数名,内函数也一样。如果不用函数名调用内函数,内函数就永远不会执行。
函数执行顺序:
代码从上至下依次执行,调用函数时函数里面从上之下依次执行
内函数的调用
首先,不能直接调用内函数 ,需要先执行外函数的代码块。
def func1():
print("这是外部函数")
def func2():
print("这是内部函数")
func2()
没有执行外函数内部的代码块,python找不到内函数,所以报name ‘func2’ is not defined,函数func2()没有定义
两种调用内函数的方法
第一种:在外函数内部调用内函数,即用函数名调用
def func1():
print("这是外部函数")
def func2():
print("这是内部函数")
func2() #函数名调用内函数
func1()
第二种:可以用return调用内函数
'''
在使用return之前,需要说明一点:我们都是使用"函数名()"调用函数的方法,单独使用"函数名”,我们会得到函数的内存
地址,使用我们return时后面跟上的函数名一定要带上括号。函数名后面加括号才会告诉python,参数是否对得上,然后执行函数的代码块。)
'''
def func1():
print("这是外部函数")
def func2():
print("这是内部函数")
return func2()
func1()
执行结果:
这是外部函数
这是内部函数
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
def func1():
print("这是外部函数")
def func2():
print("这是内部函数")
return func2
m = func1()
print(m)
执行结果为
这是外部函数
<function func1.<locals>.func2 at 0x0000000002EB6620>
def func1():
print("这是外部函数")
def func2():
print("这是内部函数")
return func2
func1()() ##执行func1()会返回func2然后再func2()
执行结果:
这是外部函数
这是内部函数
'''
小结:想要调用内函数,首先要调用外函数,即执行外函数的代码块,才有内函数调用的环境。在外函数内部,可以用函数名调用内函数。
也可以用return调用内函数,如果return是函数本身的地址,调用外函数时会用到双括号,先调用func1()得到func2
然后再func2()。如果return func2(),那么和func2()是一样的,都是告诉python调用内函数。
'''