这篇文章主要讲解了“Python函数对象的名称空间和作用域怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python函数对象的名称空间和作用域怎么使用”吧!
1.函数对象
(1)函数对象的引用
一个函数对象的形成是先定义一个函数,然后写入函数体,最后把这个函数赋值给一个变量,也就是函数的对象,然后我们可以去通过这个函数变量来实现函数相应的功能。(先赋值,再调用)
示例1:
#定义一个函数对象fun def fun(): print('hello word',end=' ') print('wwww') fun() #直接调用这个函数对象
这种写法是最直接的,没有返回值。
示例2:
def fun(): print('ww') return 123 kun = fun() print(kun,type(kun)) #输出结果:ww # 123 <class 'int'>
这个写法是定义了一个kun在变量,作为fun函数的对象,我们可以去通过这个对象去处理这个函数的返回值。
示例3:
def fun(): return 123 kun = fun print(kun,type(kun)) #输出结果:<function fun at 0x00000154828AD280> <class 'function'>
这里我没有加上()所以输出结果是fun这个变量的地址,
示例4:
def fun(): return 123 kun = fun print(kun(),type(kun)) #输出结果:123 <class 'function'>
这里先定义一个kun变量为fun的函数对象,下面如果要去调用这个函数的话就必须加上括号,如果没有括号那这个对象只是函数的地址。
(2)函数可以放到序列里面
函数的返回值是一种变量类型,同时序列可以储存变量,所以函数是可以放到序列里面去
这里就以列表为例子:
def fun(): return '牛马' kun = fun li=[1,5,kun] print(li) print(li[2]()) #输出结果:[1, 5, <function fun at 0x000001BFB1ABD280>] # 牛马
(3)函数可以作为参数 , 传递给另一个函数
示例:
def fun(): return '牛马' def ff(st): print(f'我是{st}') ff(fun()) #输出结果:我是牛马
(4)函数可以作为另一个函数的返回值
def ff(): print('我爱你') return 520 def fun(): return ff() a=fun() print(a,type(a)) #输出结果:我爱你 # 520 <class 'int'>
这里是fun函数返回值为ff函数,实际上是经历过了fun函数的功能,然后再次经历ff函数的功能,最后返回的是ff函数的520,故a的结果是520
2.名称空间
数据的名称是储存到栈区,而数据的内容是储存到堆区,当我们要去使用数据的内容时,我们可以通过数据的名称来直接去表示数据的内容,也就是通过栈区去找到堆区的东西,然后在堆区拿出来去使用。栈区和堆区是有对应关系的。
1.内建名称空间
生命周期:会随着Python启动而生成,程序关闭会摧毁
保存的数据:内置函数(input,print....)
生成顺序:程序里最先生成的
2.全局名称空间
生命周期:会随着Python启动而生成,程序关闭会摧毁
保存的数据:函数名,变量名
生成顺序:在内建名称空间的后面
3.局部名称空间
生命周期:随着函数的调用而生成,函数调用接受后就关闭
保存的数据:函数内定义的名字
生成顺序:随着函数的调用而生成
所以,我们定义的函数是属于局部名称空间,当函数被调用完成了之后就会被销毁,里面变量储存到的栈堆区都会被销毁
3.作用域
(1)作用域的理解
作用域实际上就是变量的作用范围,之前我们学了C语言都知道,有全局变量和局部变量,比如在for循环里面,里面的变量是一种局部变量,我们如果在主函数外面去定义一个变量,那就是全局变量。Python也是一样的道理,变量也是有相应的作用域。而变量的作用域是由定义的位置决定的
全局变量与局部变量的名字相同的时候,实质上是两个不同的变量, 其栈堆区是完全不一样的!所以我们不可以通过局部来改变全局变量,否则就报错
示例1:
#定义一个全局变量a a=15 def fun(): a=999 print('hhh') fun() print(a) #输出结果:15
因为函数是放到栈堆区,当函数调用完成了之后返回一个值,这个函数已经被销毁了,那么里面的变量也会与之销毁,所以不会影响到全局变量,故a的值还是15
示例2:
#定义一个全局变量a a=15 def fun(): a=999 return a print(fun()) print(a) #输出结果:999 # 15
这个函数调用完成了之后就返回一个值,这个值函数内部的功能的值,但是并没有对这个函数以外的值进行修改,所以a的结果还是15,而函数的返回值是999
示例3:
b=15 def fun(): b=b+99 fun() print(b) #输出结果:系统报错
因为b是一个全局变量,而函数里面的b是一个重新定义的局部变量,所以我们不可以去直接修改这个局部变量b,因为这个b是没有初始数值的,而且类型也未定,所以无法进行运算处理
对比
b=15 def fun(): b=0 b+=99 print(b) fun() print(b) #输出结果:99 15
对于这个而言,我给了函数里面b一个初始化值,所以可以进行运算处理,但这个b与外部全局变量的b是完全不相同,是两个不同的变量
(2)作用域的转换
在C语言中我们可以去设置静态变量(static),从而使得这个变量可以在函数进行修改,同样Python中可以利用关键字去修改变量的作用域,把局部变量作用到全局变量,或者把全局变量作用降级为局部
1.global 关键字 (局部变全局)
在函数中,变量是这个函数的局部变量,只仅仅作用到函数内部,我们对这个变量进行修改是不会影响外面的变量的,如果把这个局部变量转换为全局变量的话,那么这变量就可以在函数里面进行修改,而且还可以影响到外部,当新定义global的变量名字与之前已有的变量名字出现重复的话,新的变量内容会把之前的给覆盖掉,而且新的全局变量也可以在函数内部进行修改,从而影响全局。
注意事项:这个关键字是作用到全局变量,这个全局变量的栈堆区不会被销毁
b=15 def fun(): b=123 fun() print(b) #函数里面的b与外面的b是不同性质的!!! #输出结果:15
对比
b=15 def fun(): global b b=123 fun() print(b) #输出结果:123
重新定义了一个global后,此时这个b已经是一个新的全局变量因为前面已经有了一个全局变量b,所以这个新的全局变量会因为名字相同会把之前的全局变量b给直接覆盖掉(类似于类型相同且名字相同的文件会被新的给覆盖),故输出结果是新的全局变量b的结果:123
2.nonlocal 关键字 (全局变局部)
功能:降权,全局变成局部
前面讲到过,已知一个全局变量,但是我不可以在函数里面对这个全局变量进行修改,而且函数里面的变量都是新的变量,既是跟外面的全局变量名字一模一样,但是其储存的栈堆区是完全不同的,那么当我想去通过一个局部函数来修改这个全局变量的话,这时候我就可以通过nonlocal关键字来进行 降维处理 。
注意事项:这个关键字是作用于嵌套函数的外部变量(相较于内部函数,外部函数是“全局”),这个变量的栈堆区会被销毁
def fun(): w=99 def fun1(): w=100 fun1() return w print(fun()) #输出结果:99
VS
def fun(): w=99 def fun1(): nonlocal w w=100 fun1() return w print(fun()) #输出结果:100
这里,可以看出,w=99相对应fun1()是一个全局变量,而fun1()内部的w相对应fun()是一个局部变量,当我用nonlocal关键字去定义了fun()的变量w之后,这个w变量已经是属于fun1()函数内部的变量,这时候我们可以去修改这个w的值,从而去影响外部函数,最后w的返回值也就是被修改后的100