从零学习python - 07装饰器与高阶匿名函数

# 函数的引用 - 如果是可变类型,则不同的指向相同的内存空间的变量,操作完成后会保存.如果是不可变类型的话则修改不会保存.
a = 1
b = a
print(b)    # 1
print(id(a))    # 2288401187056 内存地址
print(id(b))    # 2288401187056 内存地址

a += 2
print(b)    # 1
print(id(a))    # 2288401187088 内存地址
print(id(b))    # 2288401187056 内存地址

list1 = [1, 2]
list2 = list1

print(list2)    # [1, 2]
print(id(list1))    # 1974503320064
print(id(list2))    # 1974503320064

list1.append(3)

print(list2)    # [1, 2, 3]
print(id(list1))    # 1974503320064
print(id(list2))    # 1974503320064
# 函数嵌套:如果外部函数内嵌套另一个内部函数,会牵扯到变量作用域的问题.一般遵循的查找顺序是:内层函数->外层函数->全局->系统定义
#       如果内部函数要修改外部函数定义的变量则需要关键字 nonlocal 变量名 来引进这个变量
#       如果全局变量想要在函数中进行修改的话则需要使用关键字 global 变量名
# 闭包:如果一个内部函数引用了外部函数作用域中的变量,并被外部函数返回,那么这个内部函数就被成为闭包(closure)

 

def outer(n):
    num = n

    def inner():
        count = num + 1
        return count

    return inner


print(outer(2)())
# 装饰器 decorator     @decorator表示调用decorator()方法,但不会执行内部函数 如果执行被@decorator标识的方法才会调用其内部函数
# 装饰器有点类似于spring boot的aop. 在满足程序开闭原则的前提下,如果需要对程序内部进行功能添加,则需要使用装饰器
# 装饰器执行顺序 -> 程序运行到@decorator时,会将下方被修饰的方法一起传入,下面例子相当于decorator(house) 将内部函数wrapper加载进内存后返回,将wrapper函数赋值给horse函数
#       装饰器功能: 引入日志 函数执行时间统计 执行函数前预备处理 执行函数后清理功能 权限校验等场景 缓存

 

def decorator(func):
    print('装饰器1')

    def wrapper():
        func()
        print('装修队装修!')

    print('装饰器2')
    return wrapper


@decorator  # decorator(house)
def house():
    print('新家毛坯房!')


house()
print('---------------')
# 有参数的装饰器1:
# 如果是原函数是带有参数的话,定义的修饰器是需要传参的,就在装饰器的内部函数中.因为传的参数不知道会有几个,所以我们用可变参数来承接.
def factory(func):
    def wrapper(*args):
        func(args)
        print('装修队装修!')

    return wrapper


@factory
def factory(address):
    print(f'新工厂毛坯房,地址在{address}')


factory('山西大同')
print('---------------')
# 有参数的装饰器2:
# 如果原函数带有参数并且还有关键字参数,则装饰器的内部函数还需要定义**kwargs来装包关键字参数
def school(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        print(args, kwargs)  # ('山西太原',) {'name': 'xx中心'}
        print('装修队装修!')

    return wrapper


@school
def school(address, name='育才中学'):
    print(f'新学校毛坯房,地址在{address},名字是{name}')


school('山西太原', name='xx中心')  # 关键字传参的话需要**kwargs接收并且以字典形式表现
print('---------------')
# 有返回值的装饰器:
# 如果原函数存在返回值的话,那么修饰器的内部函数也需要有返回值
def return_decorator(func):
    def wrapper(*args, **kwargs):
        r = func(*args, **kwargs)
        # 返回原函数的返回值
        return r

    return wrapper


@return_decorator
def print_num(num):
    return num


print(print_num(1000))  # 通过装饰器也可以接收返回值
print('---------------')
# 如果装饰器也有参数的话呢,需要在外部再调用一层.
# 流程:当程序读到@check_time(35)时,带着play_game()进入check_time(time)方法
#       第一层:check_time(time)运行:内存中读取check_play(func)方法,返回check_play
#       第二层:check_play方法并没有反出去,而是在第二层调用这个方法 check_play(play_game) 并返回wrapper内部函数
#       第三层:相当于将wrapper函数赋值给play_game函数,最后执行的就是wrapper函数
def check_time(time):
    def check_play(func):
        def wrapper(*args, **kwargs):
            if time < 30:
                func()
            else:
                print('不符合规则,不能打游戏!')

        return wrapper

    return check_play


@check_time(35)
def play_game():
    print('打游戏去喽')


play_game()  # 不符合规则,不能打游戏!
print('---------------')
# 递归实现1-10的累加和
def get_sum(i):
    if i == 10:
        # 当符合条件后,这个return会返回给最后调用他的函数,就是get_sum(9)的返回值
        return 10
    else:
        return i + get_sum(i + 1)


r = get_sum(1)
print(r)
print('---------------')
# 匿名函数 格式:lambda 参数列表: 返回值函数体表达式
r = lambda x, y: x + y
print(r(1, 2))
# 匿名函数 应用场合:匿名函数可以作为参数传递
def test_2(x, y, func):
    print(f'x={x}')
    print(f'y={y}')
    print(func(x, y))


test_2(1, 2, lambda x, y: x + y)

# 系统高阶函数:max(args, key) min(args, key) sorted(iterable, key, reverse)
#           filter(func, iterable) map(func, iterables) reduce()
# 高阶函数: 一个函数的参数是另一个函数
list_1 = [('bob', 25), ('lcy', 22), ('vob', 19), ('cd', 29), ('wdf', 20)]
# 通过key根据得到的匿名函数返回值进行排序 根据年龄排序('cd', 29)
print(max(list_1, key=lambda x: x[1]))
# 通过key根据得到的匿名函数返回值进行排序 根据年龄排序('vob', 19)
print(min(list_1, key=lambda x: x[1]))

# 通过key 匿名函数 根据年龄大小进行排序[('vob', 19), ('wdf', 20), ('lcy', 22), ('bob', 25), ('cd', 29)]
s_list = sorted(list_1, key=lambda x: x[1])  # 返回一个新列表
print(s_list)

# 如果function返回值为true则返回一个迭代器,生成该函数的可迭代对象(item)。如果function为None,则返回为true的项。
f = filter(lambda x: x[1] > 20, list_1)
print(f)  # <filter object at 0x0000023AD7A834C0>
print(list(f))  # [('bob', 25), ('lcy', 22), ('cd', 29)] 返回list中符合条件的元素

# map 创建一个迭代器,该迭代器使用的实参计算函数 将列表中每一项符合条件的元素都执行相应操作
m = map(lambda x: x[1] + 1, list_1)
print(m)    # <map object at 0x00000198BBDE3430>
print(list(m))  # [26, 23, 20, 30, 21] 返回一个新列表

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

OtnIOs

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

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

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

打赏作者

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

抵扣说明:

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

余额充值