函数对象、嵌套、名称空间与作用域以及闭包函数
目录:
一、函数对象
函数是第一类对象:指的是函数的内存地址可以像一个变量值一样去使用。(函数的内存地址指向的就是变量值)
def foo(): #foo=函数的内地址
print('from foo')
1.变量值可以被引用
x=1 #foo=函数的内存地址 y=x #将变量值1的地址给y f=foo print(f) #打印函数的内存地址 f() #调用函数
2.变量值可以当做参数传给另外一个函数
def bar(x): print(x) #打印地址 x() #调用foo函数 #foo=函数的内存地址 bar(foo) #将foo的内存地址传入bar函数
3.变量值可以当做函数的返回值
def func(x): return x f=func(foo) print(f)
4.变量值可以当做容器类型的元素
l=[foo,] print(l) #[<function foo at 0x0000000002061E18>] l[0]() #调用foo函数 dic={'1':foo} print(dic) #{'1': <function foo at 0x0000000001D11E18>} dic['1']() #调用foo函数
变量值当做容器类型元素的应用:
1 def register(): 2 print('注册....') 3 4 def login(): 5 print('登录....') 6 7 def pay(): 8 print('支付....') 9 10 def transfer(): 11 print('转账....') 12 13 func_dic={ 14 '1':register, 15 '2':login, 16 '3':pay, 17 '4':transfer 18 } 19 20 # func_dic['1']() 21 22 while True: 23 print(""" 24 0 退出 25 1 注册 26 2 登录 27 3 支付 28 4 转账 29 """) 30 choice=input('请输入你的操作: ').strip() 31 if choice == '0':break 32 33 if choice not in func_dic: 34 print('输错的指令不存在') 35 continue 36 37 func_dic[choice]()
二、函数的嵌套
1.函数的嵌套调用:在一个函数的内部又调用其他函数
#比较1,2,3,4的大小 def max2(x,y): if x > y: return x else: return y def max4(a,b,c,d): res1=max2(a,b) res2=max2(res1,c) res3=max2(res2,d) return res3 print(max4(1,2,3,4))
2.函数的嵌套定义:在函数的内部又定义了其他函数
def func(): def foo(): print('from foo') print(foo) #打印foo的地址 foo() #调用内部函数 x=1 print(x) func()
3.函数嵌套的应用:
#定义一个关于圆的函数,可以计算面积和周长 from math import pi def circle(radius,action): def cal_perimeter(): return 2 * pi * radius def cal_area(): return pi * (radius ** 2) if action == 1: res=cal_perimeter() elif action == 2: res=cal_area() return res res=circle(10,1) print(res)
三、名称空间与作用域
1.名称空间Namespaces:指的就是存放名字与值内存地址绑定关系的地方(在内存)
2.名称空间分为三大类
(1).内置命名空间:存放的是Python解释器自带的名字(变量名和函数名)
产生:python解释器的启动则产生
销毁:Python解释器关闭则销毁
(2).全局名称空间:在顶级定义的名字
x=1 #全局 if True: y=2#全局 while True: while True: while True: z=3 def func(): pass
产生:执行Python程序时产生
销毁:Python程序执行完毕则销毁
(3).局部名称空间:在函数内定义的名字
def foo(): m=100 #局部 foo()
产生:在函数调用时临时产生
销毁:在函数调用完毕后则销毁
3.三种名称空间的产生的先后顺序:内置-->全局-->局部
查找名字的顺序:从当前位置往外一层一层的查找
如果当前在局部名称空间:局部-->全局-->内置
如果当前在全局名称空间:全局-->内置
len=111 def foo(): len=222 print(len) len=111 foo() #结果为222
x=0 def f1(): x=1 def f2(): x=2 def f3(): x=3 print(x) #x=3 f3() f2() f1() def foo1(): def foo2(): def foo3(): print(x) #x=0
foo3()
foo2()
foo1()
4.作用域:指的是作用范围
全局作用域:包含内置与全局名称空间的名字
特点:全局存活,全局有效
局部作用域:包含局部名称空间的名字
特点:临时存活,局部有效
******作用域的关系在函数定义阶段就已经固定死了,与调用位置无关
示范一:
#作用域在定义阶段就已经确定f1找的是全局名称 def f1(): print(xxx) xxx=111 def f2(): xxx=222 f1() f2() #在定义阶段,f1在局部名称空间找到xxx.运行时候也只会在局部找,但是代码执行时逐行执行,先引用,后定义,所以报错 def f1(): print(xxx)#报错 xxx=111 def f2(): xxx=222 f1() f2()
示范二:
xxx=111 def f1(): print(xxx)#报错,定义时决定了作用域,不会去全局找。执行代码时逐行执行,先引用,后定义,所以报错 xxx=222 f1()
四、闭包函数
闭包函数=函数对象+函数嵌套定义+作用域
闭:封闭,指的是该函数时定义一个函数内部的函数
包:该内部函数包含对外层函数名字的引用
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
应用领域:延迟计算(原来我们是传参,现在我们是包起来)
例如:
从纽约向上海以寄快递的形式邮寄一个人,需要将人放在集装箱内(相当于闭),但是由于时间久,就必然要在集装箱内部提供水,食物等(相当于包)
示例代码:
def outter(): x=1 def inner(): print('from inner',x) return inner f=outter() #相当于 f=inner def foo(): # print(f) x=111111111111111111111111111111111111 f() foo() #结果为1
为函数传值的两种方式:
def foo(): |
方式一:直接以参数形式传入
def foo(name): print('hello %s' %name) foo('egon') foo('egon') foo('egon')
方式二:闭包函数
def outter(name): # name='egon' def foo(): print('hello %s' %name) return foo f=outter('egon') # print(f) f() f() f1=outter('alex') f1() f1()
爬取数据应用:
pip3 install requests import requests 问题 def get(): response=requests.get(url) if response.status_code == 200: print(response.text) 解决方案一: def get(url): response=requests.get(url) if response.status_code == 200: print(response.text) get('https://www.baidu.com') get('https://www.baidu.com') get('https://www.baidu.com') 解决方案二: def outter(url): # url='https://www.baidu.com' def get(): response=requests.get(url) if response.status_code == 200: print(response.text) return get baidu=outter('https://www.baidu.com') cnblogs=outter('https://www.cnblogs.com') baidu() baidu() baidu() cnblogs() cnblogs() cnblogs()
五、global
x=1 def func(): x=2 #从内存角度来说,函数内部的局部变量在内存中的地方和全局变量不在一个地方,所以不会发生变量值覆盖 func() print(x) #结果为1 x=[] def func(): x.append(1) #从全局找x,x位可变类型,追加 x.append(2) x.append(3) func() print(x)#结果[1,2,3]
# global: 在局部声明变量是全局变量 x=1 def func(): global x x=2 func() print(x)#结果为2
# nonlocal:在局部声明变量是外层函数的变量 x=333 def f1(): x=222 def f2(): x=111 def f3(): nonlocal x x=0 f3() print('f2内部的x: ',x)#0 f2() print('这是f1内部的x: ',x)#222 f1() print(x)#333