Python装饰器

函数装饰器

装饰器定义

  • 装饰器的作用就是用一个新函数封装旧函数(是旧函数代码不变的情况下增加功能)然后会返回一个新函数,新函数就叫做装饰器。
  • 一般为了简化装饰器会用语法糖@新函数来简化。
  • 装饰器是满足闭包条件的。

装饰器的用途

  • 当一个函数在很多地方调用,其中某些地方需要扩充该函数的功能,但有的地方不需要,这时候,可以加装饰器,使得需要扩充该函数功能的地方满足扩充需求。
# 并未改变原函数内容,重新定义了新的函数,扩充了原函数的内容,但是需要在扩充功能的调用处都更换函数名。
```python
# 并未改变原函数内容,重新定义了新的函数,扩充了原函数的内容,但是需要在扩充功能的调用处都更换函数名。
def food():
    print("rice, simple diet.")
def delicious_food(func):
    func()
    print("rice, vegetables and meat, delicious meal.")
delicious_food(food)

result:
rice, simple diet.
rice, vegetables and meat, delicious meal.

可以使用装饰器完成同样的功能,但是不需要改变原函数调用地方的函数名。用语法糖@新函数来简化。

"""当看到@delicious_food时,这句话会做以下2个动作:
1.将food的地址传给func, 执行delicious_food函数。
2.将其返回值wrapper送给装饰的函数名,即food。
这样在调用函数food()的时候,就会执行wrapper函数了,而其中的func地址为原food的地址,实现了功能的扩展。
"""
def delicious_food(func):
    print(func)
    print("decorate funtion")
    def wrapper():
        print("inner function")
        func()
        print("rice, vegetables and meat, delicious meal.")
    return wrapper
@delicious_food
def food():
    print("rice, simple diet.")
print(food)
food()

result:
<function food at 0x000001A516B83D08>
decorate funtion
<function delicious_food.<locals>.wrapper at 0x000001A516B83D90>
inner function
rice, simple diet.
rice, vegetables and meat, delicious meal.

内部函数带参装饰器

# 内部函数带参可以为可变参数,增强其通用性。
# @decorate之后,food指向wrapper,所以wrapper和food的参数对应,但是后面的func()对应原food,所以要和food()的参数对应。
def decorate(func):
    print("decorate funtion")
    def wrapper(*args):
        print("inner function")
        func(*args)
        print(func)
        print("rice, vegetables and meat, delicious meal.",
        "********",*args)
    return wrapper
@decorate         
def food(n):	
    print("rice, simple diet.","---------", n)
@decorate         
def food2(m,n,t):
    print("rice, simple diet.","---------", m,n,t)
        
food(10)
food2("noodles", 100, 88)

装饰器本身带参数

  • 需要有三层函数定义。
  • 第一层接收装饰器的参数,第二层接收函数,第三层接收函数的参数及调用被装饰的函数。
def outer(a):				# 接收装饰器的参数
    print(f"parameter is {a}")
    def decorate(func):		# 接收函数
        print("decorate funtion")
        def wrapper(*args):	# 接收函数的参数及调用被装饰的函数
            print("inner function")
            func(*args)
            print("rice, vegetables and meat, delicious meal.",
            "********",*args)
        return wrapper		# 返回第三层函数地址
    return decorate			# 返回第二层函数地址
@outer(10)         
def food(n):    
    print("rice, simple diet.","---------", n)
print("&&&", food) 
food(10)

result:
parameter is 10
decorate funtion
&&& <function outer.<locals>.decorate.<locals>.wrapper at 0x7fb3e104dea0>
inner function
rice, simple diet. --------- 10
rice, vegetables and meat, delicious meal. ******** 10

多层装饰器

  • 多层装饰器首先执行最靠近函数的装饰器,然后将这个装饰器返回的函数地址给外层的装饰器。
"""
1. 看到@decorate1,先去执行decorate1函数,food原函数作为参数传给decorate1的func,返回decorate1.wrapper给food。
2. 看到@decorate2,food所指向的decorate1.wrapper作为参数传给decorate2的func,返回decorate2.wrapper给food。
3. 当调用food()时,此时food所指向的是decorate2.wrapper,所以去执行它,而decorate2.wrapper中调用的func()函数,是decorate1.wrapper,而转去执行decorate1.wrapper。
4. decorate1.wrapper中的func是原函数food,所以去执行food函数。
"""
def decorate1(func):
    print("decorate1",func)
    def wrapper():
        print("decorate1 inner")
        func()
        print("decorate1, rice, vegetables")
    return wrapper 
def decorate2(func):
    print("decorate2",func)
    def wrapper():
        print("decorate2 inner")
        func()
        print("decorate1, rice, vegetables, meat, eggs")
    return wrapper  
@decorate2
@decorate1
def food():    
    print("rice, simple diet.","---------")
print("&&&", food) 
food()

result:
decorate1 <function food at 0x7ffaeb414f28>
decorate2 <function decorate1.<locals>.wrapper at 0x7ffaeb414ea0>
&&& <function decorate2.<locals>.wrapper at 0x7ffaeb42b620>
decorate2 inner
decorate1 inner
rice, simple diet. ---------
decorate1, rice, vegetables
decorate1, rice, vegetables, meat, eggs

类装饰器

  • 用于修改类的装饰器,修改类属性
# Bar传给wrap中的obj,更改了其属性后再返回给Bar。
def warp(obj):
    print("-------wrap-------")
    obj.name = 'python'
    return obj
@warp  # => Bar = warp(Bar)
class Bar(object):
    def __init__(self):
        pass

print(Bar.name)  # => python
b1 = Bar()
print(b1.name)

result:
-------wrap-------
python
python
  • 类方法装饰器
def outer(obj):  # 类方法装饰器
    print("---------outer---------")
    def inner(self):
        print('hello inner')
        obj(self)
    return inner

class Zoo(object):
    def __init__(self):
        pass

    @outer  # => zoo = outer(zoo)
    def zoo(self):
        print('hello zoo')

print("----------1----------")
zoo = Zoo()
print(zoo.zoo.__name__)
zoo.zoo()

result:
---------outer---------
----------1----------
inner
hello inner
hello zoo
  • 类对象装饰器
def wrap(cls):
    print(cls)
    class Worker:
        def __init__(self, name, age):
            self.wrapped = cls(name, age)       #创建了一个Person的实例
            print(self.wrapped)

        def display(self):
            self.wrapped.display()
            print(f'优秀工作者')
    return Worker


@wrap
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def display(self):
        print(f'这是{self.name}')

print(Person)
p1 = Person('亚瑟', 12)
p1.display()

result:
<class '__main__.Person'>
<class '__main__.wrap.<locals>.Worker'>
<__main__.Person object at 0x0000023FF6492780>
这是亚瑟
优秀工作者
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值