Python基础(第六周)

目录

一、匿名函数

匿名函数的定义

记忆内容 

二、闭包

理解引用

理解闭包

闭包实例

三、装饰器

装饰器的理解

装饰器实例


一、匿名函数

匿名函数简单理解就是没有名字的函数

匿名函数的定义

lambda 参数列表: 表达式(变量)

 匿名函数只能实现一些简单的逻辑

add_ = lambda x, y: x + y
print(add_(1, 2))  # 3


# 上述代码的实质
def test(x, y, func):
    add_ = func(x, y)
    return add_


print(test(1, 2, lambda x, y: x + y))

记忆内容 

匿名函数下面这种使用方式需要记住:

info_dict = [{'name': '小明', 'age': 19, 'gender': '男'},
             {'name': '小王', 'age': 20, 'gender': '男'},
             {'name': '小红', 'age': 18, 'gender': '女'}]

# 需求:将info_dict列表中的字典进行排序,按照age的大小从小到大排序
info_dict.sort(key=lambda x: x['age'])
print(info_dict)
'''
[{'name': '小红', 'age': 18, 'gender': '女'}, 
 {'name': '小明', 'age': 19, 'gender': '男'}, 
 {'name': '小王', 'age': 20, 'gender': '男'}]
'''

二、闭包

理解引用

def test():
    print('hello!')


test()  # 调用函数 hello!
res = test
res()  # 通过引用调用函数 hello!
print(id(test))  # 2159094682240
print(id(res))  # 2159094682240

test是我们定义的一个函数,函数名就相当于变量名,当我们定义一个变量名res等于函数名test时,res就等于是test函数的引用,指向了和test一样的内存地址

理解闭包

我们先写一个闭包程序

def test_out(num_out):
    def test_in(num_in):
        print(f'num_out的值为{num_out}')
        print(f'num_in的值为{num_in}')

        return num_in + num_out

    return test_in


# 第一种调用方法
res_ = test_out(10)
print(res_(20))
# 第二种调用方法
print(test_out(10)(20))

逐步分析闭包的逻辑:

1.先将test_out函数加入到内存中

2.res_ = test_out(10):调用test_out函数,并把参数10传给test_out函数,因为test_out函数内部只有test_in函数的定义,所以只会将test_in函数加入内存,不会执行test_in函数

3.在调用test_out函数后,执行 return test_in ,是将test_in函数的引用返回,我们用res_变量进行接收,res_就等于是test_in函数的引用,指向了和test_in一样的内存地址

4.print(res_(20)):res_就等于是test_in函数的引用,res_(20)就等于test_in函数的调用,并给test_in函数传递了参数20,调用了test_in函数,执行print(f'num_out的值为{num_out}'),输出num_out的值10,然后执行print(f'num_in的值为{num_in}'),输出num_in的值20

5.最后执行return num_in + num_out,由于我们直接打印了返回值,所以输出30

我们能否直接调用test_in函数呢?

def test_out(num_out):
    def test_in(num_in):
        print(f'num_out的值为{num_out}')
        print(f'num_in的值为{num_in}')

        return num_in + num_out

    return test_in


test_in(20)  # name 'test_in' is not defined

答案是不能,程序会报错,name 'test_in' is not defined

我们可以这么理解:

程序:我们先调用test_out函数,拿到test_in函数的引用,才能调用test_in函数

理解:我们进入客厅,拿到进入卧室的钥匙,才能进入钥匙

定义:定义一个函数,在函数内部在定义一个函数,并且这个函数用到了外部函数的局部变量,那么这个函数以及用到的变量称之为闭包

闭包三要素:

1.函数的嵌套

2.外部函数返回内部函数的引用

3.内部函数用到了外部函数的局部变量

闭包实例

需求:计算y = kx + b 的值(k,b,x不定)

def line_conf(k, b):
    def line(x):

        return k * x + b

    return line


print(line_conf(4, 5)(2))
# y = 4 * x + 5 , y = 4 * 2 + 5

三、装饰器

装饰器的理解

def f1(func):
    def f2():
        print('hello')
        func()

    return f2


@f1  # 语法糖
def f3():
    print('world')


f3()    
'''
执行结果:
hello
world
'''

python代码从上到下执行,先将f1函数加载到内存中,然后执行到@f1,这条语句会调用f1函数,并且将下面的函数(代码中是f3函数)作为参数传递给f1函数,即形参func = f3,然后f2函数中的形参func也变成f3函数

def f1(f3):
    def f2():
        print('hello')
        f3()
    return f2

因为@f1调用了f1函数并且将f3作为传输传递给了f1函数,在f1调用过程中:把f2函数加载到了内存中(并没有调用f2函数),执行return f2,此时f2已经变成了

def f1(f3):
    def f2():
        print('hello')
        
        print('world')
    return f2

print('world')是因为调用了f3函数,我们可以理解为 直接把f3函数内部的代码加到f2函数中

返回的f2函数由f3函数接收,f3函数变成变化后的f2函数

def f2():
        print('hello')
        
        print('world')

所以我们在后面调用f3函数时就等于调用了f2函数

def f2():
        print('hello')
        
        print('world')

装饰器实例

需求:在xml格式的数据中,通常可以看见类似这样的形式:<app> <id>Chrome</id> </app>

如果我们只有中间部分的字符串,如何通过装饰器给字符串加上上面形式的标签呢?

def makeAPP(fn):
    def wrapped():
        return '<app>' + fn() + '</app>'

    return wrapped


def makeID(fn):
    def wrapped():
        return '<id>' + fn() + '</id>'

    return wrapped


@makeAPP
@makeID
def slogan():
    return 'Chrome'


print(slogan())  # <app><id>Chrome</id></app>

代码中我们使用了两个装饰器,解释器从上到下执行,装饰器从下向上执行

先执行@makeID,变成<id>Chrome</id>,再执行@makeAPP,变成<app><id>Chrome</id></app>

当被装饰的函数有参数时,被装饰的函数有几个形参,装饰器的内函数就必须有几个参数

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不懂编程的大学生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值