美文网首页
12. Python之函数对象和闭包

12. Python之函数对象和闭包

作者: 随便写写咯 | 来源:发表于2021-01-17 00:15 被阅读0次

1 函数对象

精髓:可以把函数当成变量去用
# func=内存地址 定义一个函数, 实际就是给函数开辟一个内存空间
def func():
    print(func)
func()
>>
<function func at 0x00000285702A6310>

1.1 可以赋值

def func():
    print('from func')
f=func # 把func的内存地址赋值给f, 注意, 这里不能用f=func(), 这就变成了把函数的返回值赋值给f
# func()函数定义在全局, 因此, 在函数内部可以拿到
print(f,func)
f()
>>
<function func at 0x000001296AAA61F0> <function func at 0x000001296AAA61F0>
from func

函数A的内存地址复制给B
那么B()就是直接运行函数A了

1.2 可以把函数当做参数传给另外一个函数

def func():
    print('from func')

def foo(x): # x = func的内存地址
    print(x)

foo(func)

>>
<function func at 0x00000243CB3E61F0>

***********************************************************************************************************
def func():
    print('from func')

def foo(x): # x = func的内存地址
    x() # x就是func的内存地址, 因此可以直接x()运行, 就相当于运行func()

foo(func)
>> from func

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

def func():
    print('from func')

def foo(x): # x=func的内存地址
    return x # return func的内存地址

res=foo(func)
# foo(func的内存地址)
print(res) # res=func的内存地址

res()
>>
<function func at 0x0000017D038961F0>
from func

1.4 可以当做容器类型的一个元素

def func():
    print('from func')

l=[func,]
print(l)
>> [<function func at 0x000001B483FA61F0>]
l[0]()
>> from func
def func():
    print('from func')

dict1 = {'k1':func}

print(dict1['k1'])
dict1['k1']()
print(dict1)
>> 
<function func at 0x00000214317861F0>
from func
{'k1': <function func at 0x00000263299261F0>}

1.5 函数对象案例

模拟ATM功能

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


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


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

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


def register():
    print('注册')

func_dic={
    '1':login,
    '2':transfer,
    '3':check_balance,
    '4':withdraw,
    '5':register
}

# func_dic['1']()


while True:
    print("""
    0 退出
    1 登录
    2 转账
    3 查询余额
    4 提现
    5 注册
    """)
    choice = input('请输入命令编号:').strip()
    if not choice.isdigit():
        print('必须输入编号')
        continue

    if choice == '0':
        break


    if choice in func_dic:
        func_dic[choice]()
    else:
        print('输入的指令不存在')

    # if choice == '1':
    #     login()
    # elif choice == '2':
    #     transfer()
    # elif choice == '3':
    #     check_balance()
    # elif choice == '4':
    #     withdraw()
    # else:
    #     print('输入的指令不存在')


# 修正
def login():
    print('登录功能')


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


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


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


def register():
    print('注册')


func_dic = {
    '0': ['退出', None],
    '1': ['登录', login],
    '2': ['转账', transfer],
    '3': ['查询余额', check_balance],
    '4': ['提现', withdraw],
    '5': ['注册', register]
}
# func_dic['1']()


while True:
    for k in func_dic:
        print(k, func_dic[k][0])

    choice = input('请输入命令编号:').strip()
    if not choice.isdigit():
        print('必须输入编号')
        continue

    if choice == '0':
        break

    # choice='1'
    if choice in func_dic:
        func_dic[choice][1]()
    else:
        print('输入的指令不存在')
最终整理

def login():
    print('登录功能: ')
def balance():
    print('查询余额: ')
def withdraw():
    print('取款: ')
def transfer():
    print('转账: ')
# 使用字典, 存放选项和函数对象, 后期添加或者减少功能, 只需要修改字典内的元素, 并且修改函数功能即可. 对于while循环内的代码, 是不用更改的
function_dict = {
    '0':['退出',None], # 由于程序运行期间, 列表的元素是不会改的, 因此, 可以用元组代替.
    '1':['登录功能',login],
    '2':['查询余额',balance],
    '3':['取款',withdraw],
    '4':['转账',transfer],
}

while True:
    for k in function_dict:
        print(k,'>>',function_dict[k][0])
    choice = input('请输入指令: ').strip()
    if not choice.isdigit():
        print('请输入对应的数字指令: ')
        continue
    if choice == '0':
        print('退出程序!!!')
        break
    if choice in function_dict:
        function_dict[choice][1]()
    else:
        print('请输入正确的指令!!!')

2 函数嵌套

2.1 函数的嵌套调用

在调用一个函数的过程中又调用其他函数
比较大小案例

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


def max4(a,b,c,d):
    # 第一步:比较a,b得到res1
    res1=max2(a,b)
    # 第二步:比较res1,c得到res2
    res2=max2(res1,c)
    # 第三步:比较res2,d得到res3
    res3=max2(res2,d)
    return res3

res=max4(1,2,3,4)
print(res)

2.2 函数的嵌套定义

在函数内定义其他函数, 外层函数可以访问内层函数, 想让f2被所有人用到, 就放到全局, 如果想被某一个函数调用, 就写到这个函数里面嵌套
把f1当成容器看, 只有f1能用自己容器内的函数

def f1():
   def f2():
        pass
求圆形的周长和面积

def circle(radius,action=0):  # 通过action=0, 默认形参, 配合if判断, 可以实现根据传参来执行函数
    from math import pi
    # 求圆形的周长: 2*pi*radius
    def perimiter(radius):
        return 2*pi*radius

    # 求圆形的面积:pi*(radius**2)
    def area(radius):
        return pi*(radius**2)

    if action == 0:
        return 2*pi*radius

    elif action == 1:
        return area(radius)

result = circle(1,action=0)
print(result)

3 闭包函数

3.1 介绍

闭包函数=名称空间与作用域+函数嵌套+函数对象
核心点:名字的查找关系是以函数定义阶段为准

3.2 什么是闭包函数

"闭"函数指的该函数是内嵌函数
"包"函数指的该函数包含对外层函数作用域名字的引用(不是对全局作用域)
闭包函数:名称空间与作用域的应用+函数嵌套
def f1():
    x = 33333333333333333333
    def f2(): # 把f2定义在f1内, 即为闭函数, 只有该f2函数的外层函数f1能访问到
        print(x) # f2中的x引用的是其外层f1函数作用域的x, 因此, 称为包函数
    f2()


x=11111
def bar():
    x=444444
    f1()

def foo():
    x=2222
    bar()

foo()
>> 33333333333333333333

3.2.1 闭包函数应用1

名称空间与作用域的应用+函数嵌套

def f1():
    x = 33333333333333333333
    def f2():
        print(x)
    f2()


x=11111
def bar():
    x=444444
    f1()

def foo():
    x=2222
    bar()

foo()
>> 33333333333333333333

3.2.2 闭包函数应用2

基于函数对象, 实现在全局作用域拿到内层函数的内存地址
无论在哪里调用该内层函数, 其名称的查找关系都是在定义阶段确定的, 也就是其外层函数的作用域

def f1():
    x = 33333333333333333333
    def f2():
        print('函数f2:',x) # 33333333333333333333
    return f2 # 返回f2函数的内存地址, 该内存地址, 可以被f1拿到

f=f1() # f1()函数的返回值是f2函数的内存地址, 赋值给f, 那么f就等于f2的内存地址, 此时f2作为内层函数, 其内存地址可以在全局通过f访问到
print(f)

# x=4444
# f()
def foo():
    x=5555
    f()

foo()
>>
<function f1.<locals>.f2 at 0x000001AA966B5DC0>
函数f2: 33333333333333333333 # 函数f2在f1内是没有调用的, 只有当执行了foo函数内部代码f()时, 才是调用f2函数. 因此, f2内部的print是后执行的

4 函数传参的两种方式

为何要有闭包函数=》闭包函数的应用
两种为函数体传参的方式

4.1 利用实参给形参传参

直接把函数体需要的参数定义成形参

def f2(x):
    print(x)

f2(1)
f2(2)
f2(3)

4.2 利用闭包函数

利用名称空间, 使用闭包函数传参

def f1(x): # x=3
  # x=3
    def f2(): # 实际需要用的函数是f2, 但是因为f2写在了f1内, 因此, 在全局是无法调用的, 需要利用函数对象, 把f2的内存地址, 传给全局的变量x
        print(x)
    return f2

x=f1(3) # 给f1传3, 就相当于在f1内部, 定义x=3, 然后被f2调用. 
print(x)

x()
>>
<function f1.<locals>.f2 at 0x000001E7DAFF5DC0> # 先调用f1, 把返回的
# f2的内存地址, 赋值给全局变量x, 之后print(x), 拿到f2的内存地址
3 # 最后调用x(), 才是执行f2函数的代码, print(x), f2的x在定义阶段已经确定, 需要使用
# 外层f1内的x的值

4.3 闭包函数传参案例

import requests

传参的方案一:通过实参给形参传参
def get(url):
    response=requests.get(url)
    print(len(response.text))

get('https://www.baidu.com')
get('https://www.jianshu.com')
get('https://www.zhihu.com')

>>
2443
584
166


传参的方案二:利用闭包传参
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() # 之后再运行内层函数

jianshu=outter('https://www.jianshu.com/')
jianshu()

zhihu=outter('https://www.zhihu.com/')
zhihu()

相关文章

  • python函数之闭包

    目录 python函数之闭包什么是闭包python中的namespace闭包的条件闭包的优点 python函数之闭...

  • 12. Python之函数对象和闭包

    1 函数对象 1.1 可以赋值 1.2 可以把函数当做参数传给另外一个函数 1.3 可以把函数当做另外一个函数的返...

  • python之理解闭包和装饰器

    python之理解闭包和装饰器 1、闭包函数 1.1 python中函数都是对象 结果: 上面定义一个shut函数...

  • 函数对象和闭包

    函数对象和闭包 一) 函数对象 示例: 二)函数嵌套 三)闭包函数

  • Python高级第五天

    闭包和装饰器 一、魔法方法之__call__ 在Python中,函数其实是一个对象,所有的函数都是可调用对象,一个...

  • Python装饰器(Decorator)完全指南-基础篇

    Decorator基本指南 前提知识 Python中的闭包(closure) 所谓闭包,指的是附带数据的函数对象。...

  • Python 入门之 闭包

    Python 入门之 闭包 1、闭包 (1)在嵌套函数内使用(非本层变量)和非全局变量就是闭包 (2)_ clos...

  • Python闭包函数和装饰器

    2018年7月2日笔记 7.Python函数对象和闭包 1.函数对象 函数是对象,可以给函数增加属性 上面一段代码...

  • Python 闭包与装饰器图解

    python万物皆对象! 闭包 闭包:两个函数的嵌套,外部函数返回内部函数的引用,外部函数一定有参数 def 外部...

  • python闭包函数与装饰器函数

    一、闭包函数 什么是闭包:python是一种面向对象的编程语言,在python中一切皆对象,这样就使得变量所拥有的...

网友评论

      本文标题:12. Python之函数对象和闭包

      本文链接:https://www.haomeiwen.com/subject/ofabaktx.html