函数是第一类对象,函数名指向的值可以被当作参数传递。
1),函数名可以被传递;就像变量赋值一样,把值赋给变量名,再把这个变量名传递给其他的变量名。
name='niuer' x=name 此时x也就等于‘niuer’,x和name 同时指向‘niuer’的内存地址
而函数被调用执行完函数体代码以后,打印函数名(不加括号),返回的是函数体代码的内存地址。如下图所示。
2),函数名可以被当做参数传递给其他函数
图中,我们直接将函数func()的函数名直接以参数的方式传递给index函数,在index()函数体内部先打印func,即是func函数体代码对应内存地址,然后执行args(),即是执行func()函数,进入func()函数体内部执行代码,之后再打印‘fromindex’。
3.函数名可以被当做函数的返回值
首先执行func()的函数体代码,return返回index,然后参数传递给res,再加上括号,相当于调用index函数
4.可以被当做容器类型的元素
def func(): print('from func') func_list = [func] func_list[0]() #from func
二、名称空间
什么是名称空间?
名称空间就是用来存放名字与值内存地址绑定关系的地方(内存空间),但凡查找值一定要通过名字,访问名字必须去查找名称空间。
名称空间的分类
内置名称空间:存放的是Python解释器自有的名字
#print(len)#print(max)
全局名称空间:存放的是文件级别的名字
x=1 while True def foo():
y=2 b=4 m=3
if x==4: break
z=3
局部名称空间:在函数内定义的名字
生命周期:
内置名称空间:在解释器启动时生效,解释器关闭则失效
全局名称空间:在解释器执行Python文件时生效,文件执行完毕后则失效。
局部名称空间:只在调用函数是临时产生该函数的局部名称空间,该函数调用额按笔后则 失效。
加载顺序:内置》全局》局部
名字的查找顺序:
基于当前所在位置往上查找,假设当前站在局部,查找从局部到全局到内置;假设当前站在全局,查找顺序为从全局到内置。
名字的查找顺序在函数的定义阶段就已经固定死了,与函数的调用位置无关。也就是说无论在任何地方调用函数都必须回到当初定义函数的位置去确定名字的查找顺序。
三、函数嵌套
定义:函数内部定义的函数,无法在函数外部使用内部定义的函数;
def f1(): def f2(): print('from f2') f2() f2() # NameError: name 'f2' is not defined
def f1(): def f2(): print('from f2') f2() f1() ''' from f2 '''
#函数嵌套应用事例 ''' 给一个函数传参即可求得某个圆的面积或者圆的周长 ''' from math import pi def circle(radius,nums): ''' area:圆的面积 perimeter:圆的周长 :param radius: 圆的半径 :param nums: 选择1求圆的面积,输入2求圆的周长; :return: ''' def area(): return radius**2*pi def perimeter(): return 2*pi*radius if nums==1: return area() elif nums==2: return perimeter() else: return f'输入{nums}不正确!无法计算!' print(circle(10,1)) print(circle(10,2)) print(circle(10,3))
四、作用域:
域指的是范围,作用域指的是作用的范围,分为两种。
全局作用域:包含的是内置名称空间,与全局名称空间的名字。特点:全局有效,全局存活。
局部作用域:包含的是局部名称空间中的名字。特点:局部有效,临时存活。
global,nonlocal
global:在局部声明一个名字是来自全局作用域的,可以用来在局部修改全局的不可变类型,不论外面套了多少层函数都是修改最外层的作用域。
nonlocal:声明一个名字是来自当前层外一层作用域的,可以用来在局部修改外层函数的不可变类型。