函数对象和闭包

blog 129

函数对象

函数对象指的是函数可以被当做一个数据去处理。下面我们可以使用以下几个例子介绍

函数可以被赋值

# func = 内存地址
def bar():
    print('from bar')


demo = bar # 将函数bar的内存地址赋值给变量demo
print(demo,bar) # <function bar at 0x7f9a400e3268> <function bar at 0x7f9a400e3268>
demo() # from bar

可以当做函数的参数传入

# func = 内存地址
def bar():
    print('from bar')


def foo(x): # x => bar的内存地址
    print(x) # 打印bar的内存地址
    x() # 调用bar()函数

foo(bar) # foo(bar的内存地址)

可以把函数当做另外一个函数的返回值

# func = 内存地址
def bar():
    print('from bar')

def wrapper(y): # y => bar的内存地址
    return y # 返回bar的内存地址给当前这个函数
res = wrapper(bar) # wrapper(bar的内存地址)
res() # 调用res()相当于调用bar()
print(res) # res的内存地址就是dmeo的内存地址

可以当做容器类型的元素

# func = 内存地址
def bar():
    print('from bar')

l = [demo,]
l[0]()

ATM提款机功能简单实现

def login():
    print('登录功能')

def transfer():
    print('转账功能')

def check_banlance():
    print('查询余额')

def withdrawal():
    print('提现')

dic_func = {
    '0':('退出',None),
    '1':('登录',login),
    '2':('转账',transfer),
    '3':('查询余额',check_banlance),
    '4':('提现',withdrawal)
}

while True:
    for key in dic_func:
        print(key,dic_func[key][0])
    choice = input('请输入命令执行编号: ').strip()
    if not choice.isdigit():
        print('您输入的命令非法! ')
        continue
    if choice == '0':
        break
    if choice in dic_func:
        dic_func[choice][1]()
    else:
        print('您输入的命令不存在')

函数嵌套

函数嵌套调用:在调用一个函数的过程中,又调用另外一个函数

# 传入4个参数,打印出四个数中的最大值

def max2(x,y):
    if x > y:
        return x
    else:
        return y

def max4(a,b,c,d):
    # 第一步: 比较a和b得出res1
    res1 = max(a,b)
    # 第二步: 比较c和d得出res2
    res2 = max(c,d)    
    # 第三步: 比较res1和res2得出res3
    res3 = max(res1,res2)
    return res3
print(max4(10,20,30,50))

函数嵌套定义:在函数内定义其他函数

def f1():
    def f2():
        pass


from math import pi, radians

def circle(radius,action=0):
    # 求圆形的周长: 2*pi**radius

    def perimiter(radius):
        return 2 * pi ** radius

    # 求圆形的面积: pi*(radius**2)
    def area(radius):
        return pi * (radius ** 2)
    if action == 0:
        return perimiter(radius)
    else:
        return area(radius)
print(circle(30))

闭包函数

前提

闭包函数=名称空间+作用域+函数嵌套+函数对象

核心点:名字的查找关系是以函数定义阶段为准

闭包函数的概念

"闭":函数指的是该函数是内嵌函数

“包”:函数指的是该函数包含对外层函数作用域名称的引用

# 闭包函数示例
def f1():
    x = 123
    def f2():
        print(x)

    return f2

res = f1()
res()
print(res) # <function f1.<locals>.f2 at 0x7fd2002667b8>

也就是说,函数被当做数据处理的时候,始终以自带的作用域为准,若内嵌函数包含对外部函数的作用域(非全局作用域)中变量的引用,那么该内嵌的函数就是闭包函数。简称闭包。

可以通过函数的__closure__属性去查看当前闭包函数所包含的外部变量的值

# 闭包函数示例
def f1():
    x = 123
    a = 456
    def f2():
        print(a)
        print(x)

    return f2

res = f1()
res()
print(res.__closure__) # (<cell at 0x7f8540139fa8: int object at 0x7f85400f4e70>, <cell at 0x7f8540174618: int object at 0x10b3d4b40>)
print(res.__closure__[0].cell_contents)  # 456
print(res.__closure__[1].cell_contents)  # 123

"闭"代表函数是内部的,而“包”则是函数内包含着对外层函数的引用。因此无论在何处调用闭包函数,使用的仍然是包裹其外的变量。

闭包的用途

目前我们对于函数传参学过两种传参方式,一种是将值以参数的方式传入,第二种则是将值包给函数。

import requests 

# 第一种: 
def get(url):
    res = requests.get(url)
    print(res.text)

get('https://www.baidu.com') # 直接在调用函数的时候传入参数

# 第二种:

def page(url):
    def get():
        return requests.get(url).text
    return get
get = page('https://www.taobao.com')
print(get())

分享