函数对象与闭包


函数对象(函数名)

**"""函数名遇到括号就会调用!!!"""** ![image](https://img2020.cnblogs.com/blog/2611124/202111/2611124-20211116184319326-1342682533.png)
# 用法1:函数名可以当做变量名赋值
def index():
    print('from index')
a = index
a()  # 本质就是在调用index函数
# 用法2:函数名还可以当做函数的实参
def index():
    print('from index')
def func(a):
    print(a)
    a()
    print('from func')
func(index)

# 用法3:函数名还可以当做函数返回值
def index():
    print('from index')
def func():
    print('from func')
    return index
res = func()  # 调用func并接受func的返回值
res()

# 用法4:函数名可以当做容器类型(内部可以存放多个数据)的元素
def index():
    print('from index')
l = [111, 222, 333, index()]
print(l)

现在我们回过头来看函数版的登录注册功能,可以提前搭个框架再往下写了。

# 框架
def register():
	print('注册功能')
def login():
	print('登录功能')
def shopping():
	print('购物功能')
def transfer():
	print('转账功能')
def withdraw():
	print('提现功能')
def check_order():
	print('查看订单')
	# 调用函数,建个字典
func_dic = {'1':register,
			'2':login,
			'3':shopping,
			'4':transfer,
			'5':withdraw,
			'6':check_order
			}
while True:# 开启循环
	print("""
	1.注册功能
	2.登录功能
	3.购物功能
	4.转账功能
	5.提现功能
	6.查看订单
	""")
	choice = input('请输入功能编号>>>:').strip()
	# 判断用户输入的编号在不在字典的k中
	if choice in func_dic:
		# 根据键获取值(函数名)
		func_name = func_dic.get(choice)
		# 函数名加括号调用
		func_name()
	else:
		print('功能编号不存在')

	# 下列代码的弊端在于功能较多时 代码过于复杂
	if choice == '1':
	    register()
	elif choice == '2':
	    login()
	elif choice == '3':
	    shopping()
	elif choice == '4':
	    transfer()
	elif choice == '5':
		withdraw()
	elif choice == '6':
		check_order()
	else:
		print('其余功能暂未开放!')

函数的嵌套调用

# 嵌套调用:函数内部调用其他函数
def index(): # 定义一个函数index
    print('from index') # index的函数代码体
def func():# 定义一个函数func
    index()# 调用index函数
    print('from func')# func的函数代码体
func()# 执行func()函数。
# 返回结果:
	from index
from func

再来一个函数代码,用来比大小,我们之前是这样做的。

def my_max(a, b):# 定义一个函数my_max
	if a > b:  # 判断:如果a > b
		return a  # 那么返回a(如果条件不成立,那么这行代码不执行。)
	return b  # 否则返回b

现在我们可以用函数嵌套,同时比4个大小

def my_max(a, b):
	if a > b:
		return a
	return b

def many_max(x,y,z,m): # 定义另外一个函数many_max
	res = my_max(x,y) # 将xy传入函数my_max.此时res拿到的xy里面较大的那个数
	res1 = my_max(res,z) # 再拿x,y里较大的数和z比,较大的数赋值给res1
	res2 = my_max(res1,m)  # 再拿res1的值去和m比
	return res2  # 返回res2.
ret = many_max(1,2,3,4)# 可以传数值了.将4个数值比出来结果赋值给ret.
print(ret)# 返回结果是4

函数的嵌套定义

# 函数体内部定义其他函数
# 将复杂的功能全部隐藏起来 暴露一个简单的接口
def all_func(type):
    def register():
        print('注册功能')
    def login():
        print('登录功能')
    def transfer():
        print('转账功能')
    def shopping():
        print('购物功能')
    # 这里仅仅是延时嵌套定义的现象 暂不考虑优化
    if type == '1':
        register()
    elif type == '2':
        login()
    elif type == '3':
        transfer()
    elif type == '4':
        shopping()
    else:
        print('不知道啥功能')

all_func('3')

闭包函数

闭:定义在函数内部的函数
包:内部函数使用了外部函数名称空间中的名字
# 只有符合上述两个特征的函数才可以称之为"闭包函数"

def outer():
    x = 222
    def index():
        print('from index', x)
    return index

# 闭包函数其实是给函数传参的第二种方式
# 方式1:函数体代码需要用到数据 直接在括号内定义形参即可
def index(username):
    print(username)
def my_max(a, b):
    if a > b:
        return a
    return b
# 方式2:利用闭包函数
def outer(x,y):
    x = 2
    y = 40
    def my_max():
        if x > y:
            return x
        return y
    return my_max
res = outer(2,40)
print(res())   返回结果是:40





















### 闭包的用途


目前为止,我们得到了两种为函数体传值的方式,一种是直接将值以参数的形式传入,另一种就是将值包给函数:

方式一:

import requests
 
def get(url):
    return requests.get(url).text
方式二:

import requests

def page(url):
    def get():
        return requests.get(url).text
    return get
提示:requests模块是用来模拟浏览器向网站发送请求并将页面内容下载到本地,需要事先安装:pip3 install requests

对比两种方式,方式一在下载同一页面时需要重复传入url,而方式二只需要传一次值,就会得到一个包含指定url的闭包函数,以后调用该闭包函数无需再传url:

方式一下载同一页面:

get('https://www.python.org')
get('https://www.python.org')
get('https://www.python.org')
……
方式二下载同一页面:

python = page('https://www.python.org')
python()
python()
python()
……
闭包函数的这种特性有时又称为惰性计算。使用将值包给函数的方式,在下一篇的装饰器中也将大有用处。

相关