函数对象与闭包
一、函数对象
函数对象的本质:函数对象的本质是是一个变量,它可以被引用、可以作为一个容器对象的元素、可以作为函数的参数,甚至可以是一个函数的返回值。
(1)作为被引用的对象
def student(name, age, gender='male'): # student --> 0xffee0fc2 print('{0}的信息如下:\n姓名:{0}\n年龄:{1}\n性别:{2}'.format(name, age, gender)) s = student # s -->0xffee0fc2 s('王鹏',18) s('姜春',18,gender='female')
(2)作为一个容器对象的元素
#!/usr/bin/env python # -*- coding:utf-8 -*- from prettytable import PrettyTable def login(): print('登录功能!') def save(): print('存钱功能!') def transfer(): print('转账功能!') def withdraw(): print('取钱功能!') def check_banlance(): print('查询余额功能!') def register(): print('注册功能!') func_choice= { '0': ('退出', None), '1': ('登录', login), '2': ('存钱', save), '3': ('转账', transfer), '4': ('取钱', withdraw), '5': ('查询余额', check_banlance), '6': ('注册', register) } def atm_interface(): while True: tb = PrettyTable(field_names=['功能编号', '功能名称']) for k in func_choice: tb.add_row([k, func_choice[k][0]]) print(tb) user_choice = input('请输入功能编号:').strip() if not user_choice.isdigit(): print('请输入一个正整数!') continue elif user_choice == '0': break elif user_choice in func_choice: func_choice[k][1]() else: print('该功能尚未支持!') _continue = input('是否继续(y,n):').strip().lower() if _continue == 'y': continue else:break atm_interface()
(3)作为一个参数传入另外一个函数
def outter(func): def wrapper(): res = func() print('hello,oldboy!') return res return wrapper def test(): print('hello,shanghai!') test = outter(test) test()
sudo+ssh://root@192.168.80.130:22/usr/bin/python -u //practice/day16/practice_4.py hello,shanghai! hello,oldboy!
(4)函数的返回值可以是一个函数
def student(): print('hello, oldboy!') def test(func): print(func) return func print(student) test(student)() sudo+ssh://root@192.168.80.130:22/usr/bin/python -u //practice/day16/practice_4.py <function student at 0x7ffb17de3ee0> <function student at 0x7ffb17de3ee0> hello, oldboy!
二、函数的嵌套
(1)函数的嵌套调用
在函数的调用过程中,又调用了其他的函数
def mymax(x,y): return x if x>y else y def vmax(a,b,c,d): res1=mymax(a,b) res2=mymax(c,d) return mymax(res1,res2) print('[4,6,1,3]中最大的数是:{}'.format(vmax(4,6,1,3)))
(2)函数的嵌套定义
在函数的定义过程中,包含另外一个函数的定义
#!/usr/bin/env python #-*- coding:utf-8 -*- from math import pi def circle(radius,action=0): """ action参数:(0,1) 0 -->求圆的周长 2*pi*radius 1 -->求圆的面积 pi*(radius**2) """ def perimeter():return 2*pi*radius def area():return pi*(radius**2) if action == 0: res = perimeter() else:res = area() return res print('半径为4的圆的周长为:{:.2f}'.format(circle(4))) print('半径为6的圆的面积为:{:.2f}'.format(circle(6,action=1)))
三、闭包函数
# 闭包函数=名称空间与作用域+函数嵌套+函数对象
核心点:名字的查找关系是以函数定义阶段为准
(1)‘闭’与‘包’
# 闭”函数:该函数是内嵌函数 # 包"函数:该函数包含对外层函数作用域名字的引用(不是对全局作用域)
# 闭包函数:名称空间与作用域的应用+函数嵌套 def f1(): x = 2333 def f2(): print(x) f2() # 闭包函数:函数对象 def f1(): x = 2333 def f2(): print(x) return f2 f = f1() f()
(2)闭包的用途
向函数传参的另外一种方式
# 两种为函数体传参的方式 # 方式一:直接把函数体需要的参数定义成形参 def f2(x): print(x) f2(1) f2(2) f2(3) # 方式二: def f1(x): # x=3 x=3 def f2(): print(x) return f2 x=f1(3) print(x) x() # 应用场景 import requests # 传参的方案一: def get(url): response=requests.get(url) print(len(response.text)) get('https://www.baidu.com') get('https://www.cnblogs.com/linhaifeng') get('https://zhuanlan.zhihu.com/p/109056932') # 传参的方案二: def outter(url): # url='https://www.baidu.com' def get(): response=requests.get(url) print(len(response.text)) return get baidu=outter('https://www.baidu.com') baidu() cnblogs=outter('https://www.cnblogs.com/linhaifeng') cnblogs() zhihu=outter('https://zhuanlan.zhihu.com/p/109056932') zhihu()