函数对象、函数嵌套、函数的名称空间与作用域
1、函数对象
#函数是第一类对象的含义是函数可以被当作数据处理----------所以函数即变量这么一说 # def func(): #func=<function func at 0x0584BA50> #变量名对应的就是一个内存地址 # print('from func') # # print(func) # # x='hello' # #1、引用 # y=x #变量x可以被y引用 # f=func #函数名func也类似于变量名可以被f引用 # print(f) # f() #f对应的是内存地址,所以加括号就会被调用 #2、当作参数传给一个函数 # len(x) # def foo(m): # print(m) #打印的是函数的变量名即该函数的内存地址,<function func at 0x000001FDC6813BF8> # m() #内存地址传给m,所以加括号即能被调用 # # foo(func) #3、可以当作函数的返回值 def foo(x): #x=func return x #return func #当调用函数foo时,会将函数名func返回,即func的内存地址返回 res=foo(func) print(res) res() #4、可以当作容器类型的元素 # l=[x,] #变量名可以放进一个容器中 # l=[func,] #韩说明同样可以刚入到一个容器中 # # print(l) # # l[0]() #从容器中取出函数名,加括号即调用该函数 # 函数对象的应用场景 def pay(): print('支付。。。') def withdraw(): print('取款。。。') def transfer(): print('转账。。。') def check_balance(): print('查看余额。。。') def shopping(): print('购物。。。') #将函数名放到容器中 func_dic={ '1':pay, '2':withdraw, '3':transfer, '4':check_balance, '6':shopping } while True: msg=""" 1 支付 2 取款 3 转账 4 查看余额 5 退出 6 购物 """ print(msg) choice=input('>>: ').strip() if choice == '5':break if choice not in func_dic: print('输入的指令不存在傻叉') continue func_dic[choice]()
2、函数嵌套
#函数的嵌套定义 # def f1(): # def f2(): #在函数内部在嵌套一个或多个函数 # print('from f2') # f2() # f1() #函数嵌套的应用 # from math import pi #定义一个圆的函数,嵌套的好处,每次想只想圆相关的功能(算圆的面积和圆的周长),直接调用圆就可以了 # def circle(radius,action='area'): #radius=10 # def area(): # return pi * (radius ** 2) # # def perimeter(): # return 2 * pi * radius # # if action == 'area': # return area() #外层函数调用直接拿到计算面积函数名并调用,通过返回值调用计算面积的函数,并拿到计算面积的最终结果 # elif action == 'perimeter': # return perimeter() # print(circle(10)) # print(circle(10,action='perimeter')) #函数的嵌套调用 # def max2(x,y): # if x > y: # return x # else: # return y # # def max4(a,b,c,d): #每次计算两个值得大小,不用重新写if判断,减少代码冗余 # res1=max2(a,b) #将函数嵌套在max4中进行调用,通过调用max4间接的调用max2函数进行比较大小 # res2=max2(res1,c) #拿到两者中较大的值,在与下一个值进行一决高下 # res3=max2(res2,d) # return res3 #要通过return将比较大小中最大的结果返回,否则调用的时候结果为None # # print(max4(1,2,3,4))
3、函数的名称空间与作用域
''' 1、名称空间namespaces 存放名字与值绑定关系的地方 2、名称空间分为三大类 内置名称空间: 作用:存放python解释器自带的名字 生命周期: 在解释器启动时生效,在解释器关闭时失效 全局名称空间: 作用:除了内置的与局部的名字外,其余都是全局名字 生命周期: 在文件执行时生效,在文件执行完毕时失效 例如:x,func,y,l,z都是 x=1 def func(): a=1 y=2 l=[1,2] if 3 > 2: if if if z=3 #if内套一万层其也是全局名称空间。。。。。。 局部名称空间: 作用:用于存放函数调用期间函数体产生的名字 生命周期: 在文件执行过程 如果调用了某个函数才会临时生效,在函数执行完毕后失效 三种名称空间的加载顺序是: 内置-》全局-》局部 名称空间就是用来存放名字与值的绑定关系的,所以但凡要查找名字 一定是从三者之一找到,查找顺序: 从当前所在的位置倒着查找,如果当前所在的位置是局部名称空间, 则查找顺序是: 局部-》全局-》内置 3、作用域: #----------------本质就是对名称空间的进一步的分类,并没有增加新的知识点 域指的是区域、范围,作用域即作用的范围 全局作用范围,全局作用域(内置名称空间与全局名称空间) 全局有效,全局存活 局部作用范围,局部作用域(局部名称空间) 局部有效,临时存活 ''' x=1 # len=100 def func(): y=2 # len=1000 print(len) #从当前开始找,有会打印en=1000,将len=1000注释掉,局部没有回去全局找len=100,全局注释掉会去内置找,内置有会打印<built-in function len> # print(a) #从当亲开始找,一直找到内置都没有找到,就会报错-------NameError: name 'a' is not defined # func() # print(len) #全局直接打印,会到内置中去找,结果是<built-in function len> # def func(): # y=2 # print(x) # # x=1 #全局名称空间,存放全局的名字与全局值得绑定关系的地方,值有存放的地方,名字也有自己存放的地方 # func() #在函数定义阶段,x=1已经被定义,所以调用func时,局部没有回到全局找,最终调用打印结果为1 # x=10 # x=1 # def f1(): # def f2(): # def f3(): # zzz=333 # print(x) #自己没有,从自己开始往上找,f2中有所以就不会再往上找,所以打印结果是22222 # x = 22222 # f3() # # x=111111 # f2() # # # def bar(): # print(x) #自己没有去全局找,所以打印结果是1 # # f1() # bar() # 作用域关系是在函数定义阶段就固定死了,但凡调用函数都需要跑到定义阶段去找作用域关系 # x=1 # def f1(): # print(x) #在调用函数f1时,x已经被改成了x=1000000000000000000000000000000,所以调用结果为x=1000000000000000000000000000000 # # f1() # x=1000000000000000000000000000000 # def f2(): # # print(f1) # x=11111111111111111 # f1() # # f2() #函数对象+作用域:******----------(***重点***) def f1(): x=1 def inner(): print('from inner',x) return inner #函数对象可以当做返回值,将内部的函数名返回到外部,打破层级的限制 f=f1() #调用f1拿到返回的结果即内部函数inner即inner的内存地址,内存地址加括号就可以被调用 print(f) #打印的是f1内部函数inner的内存地址------------<function f1.<locals>.inner at 0x000002709B7C3BF8> def bar(): x=111111111111111111111111111111111111111111111 f() #打破层级的限制,函数f1外部,即bar函数内部调用f1内部的函数inner,f本质就是inner,加括号即调用,但凡调用都要回到定义阶段去找定义关系 bar() # # x=1 # def foo(): # global x #将x声明为全局变量,会将全局的变量x=1改为x=2 # x=2 # # foo() # print(x) #已经将x=1声明为x=2了,所以调用后打印结果即为2 # # x=1 #x为不可变的全局变量,如果要想修改他,就需要借助glabal将函数内部的x声明为全局变量 # def f1(): # def f2(): # x=22222222 # def f3(): # global x #任然是将x=11111111111111111声明为全局变量,所以并不会影响到局部其他的变量x的值 # x=11111111111111111 # f3() # f2() # # f1() # print(x) #打印结果任然为11111111111111111 # x=1 # def f1(): # # x=33333 # def f2(): # # x=22222222 #没有被注释时,会被声明为 x=2000000000 # def f3(): # nonlocal x #将局部变量 x=20000000000声明为局部的名称空间,如果局部没有与之对应放入变量就会报错,即# x=22222222和 # x=33333就会报错 # x=20000000000 # f3() # print(x) # f2() # # f1() # print(x) # 在局部如果想要修改全局的可变类型,不需要借助任何声明,可以直接修改 # 在局部如果想要修改全局的不可变类型,需要借助global声明,声明为全局的变量就可以直接修改了 # x=[] # def f1(): # x.append(1) #修改全局的可变类型x=[],不需要借助任何声明,就可以完成对x=[]的修改 # f1() # f1() # print(x)
python之基础知识大全