python装饰器

1、装饰器,基本格式

def shout(word='yes'):
    return word.capitalize()
scream=shout
def do_something_before_fun(func):
    print("do something before ")
    print(func())

do_something_before_fun(scream)

def my_new_decorator(a_function):
    def wrapper_fun():
        print("before function")
        a_function()
        print("after function")
    return wrapper_fun

@my_new_decorator #语法糖
def another_alone_func():
    print("i am alone func")

# func=my_new_decorator(another_alone_func) #@my_new_decorator 是该条语句简写
# func()
another_alone_func()

2、堆积使用装饰器

# 堆积使用装饰器
def bread(func):
    def wrapper():
        print("</''''''\>")
        func()
        print("<\______\>")
    return wrapper

def ingredients(func):
    def wrapper():
        print("#tomatoes#")
        func()
        print("~salad~")
    return wrapper
@bread
@ingredients  # 相当于:sandwich=bread(ingredients(sandwich))
#装饰器的放置顺序很重要
def sandwich(food="--ham---"):
    print(food)
sandwich()

3、给装饰器传递参数

def a_decorator_passing_argus(func):
    def a_wrapper_accepting_argus(args1,args2):
        print("i got args! look:",args1,args2)
        func(args1,args2)
    return a_wrapper_accepting_argus

@a_decorator_passing_argus
def print_full_name(args1,args2):
    print("my name is :", args1,args2)

print_full_name("li","si")

4、含参数的装饰器

pre_str 是允许参数的装饰器,实际上是对原有装饰器的一个函数封装,并返回一个装饰器。我们可以将他理解为
一个含有环境变量的闭包。当我们使用@pre_str(‘_’)调用的时候,python能够发现这一层的封装,并
把参数传递到装饰器的环境中,该调用相当于:
sum_ab=pre_str(“_”)(sum_ab)
闭包:至少两层楼,楼下变量管上楼,return上楼不动手(不动手即返回函数对象,不带(括号))
装饰器:客人空手来,还得请上楼,干啥都同意,有参给上楼
函数作用域:
1、作用域事栋楼,下楼套上楼
2、读变量,往下搜,一直到一楼
3、该变量,莫下楼,除非你放狗(global)
闭包:函数嵌套,内部函数使用外部函数的变量或者参数,外部函数返回内部函数,这个使用了外部函数变量的内部函数称为闭包

装饰器:实际上也是一个闭包,也是一个函数嵌套;但是装饰器这个闭包函数,他的参数有且只有一个并且是函数类型,这样才是装饰器,否则就是闭包函数

#含参数的装饰器
#新的装饰器层级 def pre_str
def pre_str(pre=""):
    #旧的装饰器层级
    def decorator(func):
        def wrapper(a,b):
            print(pre+"input",a,b)
            return func(a,b)
        return wrapper
    return decorator

@pre_str("^_^")
def sum_ab(a,b):
    return a+b

print(sum_ab(2,3))

5、装饰类中的方法

python函数和方法几乎是一样的,出了方法的第一个参数是self;装饰器可以装饰函数,就同样可以
装饰类中的方法,记住带上self

装饰类中的方法
def method_decorator(method_to_decorate):
    def wrapper(self,line):
        line=line-3
        return method_to_decorate(self,line)
    return wrapper

class lucy():
    def __init__(self):
        self.age=32

    @method_decorator
    def say_age(self,line):
        print("my age is %s"%(self.age+line))
l=lucy()
l.say_age(-3)

6、通用装饰器

def a_decorator_passing_arguments(func):
    def a_wrapper_accepting_arguments(*args, **kwargs):
        print("do i have args:?")
        print(args)
        print(kwargs)

        func(*args, **kwargs)

    return a_wrapper_accepting_arguments


@a_decorator_passing_arguments
def func_with_no_argument():
    print("i have no arguments")

func_with_no_argument()

@a_decorator_passing_arguments
def func_with_argument(a,b,c):
    print(a,b,c)

func_with_argument(1,2,3)

@a_decorator_passing_arguments
def func_with_many_arguments(a,b,c,payout="why not"):
    print(a,b,c,payout)

func_with_many_arguments(2,3,4,payout="nihao")
class Mary():
    def __init__(self):
        self.age = 32

    @a_decorator_passing_arguments
    def say_age(self, line=-3):
        print(self.age + line)


m = Mary()
m.say_age()

7、装饰类

装饰器可以接受一个类,并返回一个类,从而起到加工类的效果``
decorator中,返回一个新类newClass,在新类中,记录原来类生成的对象(self.wrapped)
附加了新的属性total_display,用于记录display的次数。同时更改了display方法,通过修改
调用bira类就可以显示调用display的次数了

def decorator(aClass):
    class newClass:
        def __init__(self,age):
            self.total_display=0
            self.wrapped=aClass(age)
        def display(self):
            self.total_display+=1
            print("total display",self.total_display)
            self.wrapped.display()
    return newClass

@decorator
class Bird:
    def __init__(self,age):
        self.age=age

    def display(self):
        print("my age is ",self.age)

cl=Bird(5)
for i in range(3):
    cl.display()

8、内置装饰器

python中经常用到的三种装饰器,property,static method,classmethod,共同点,作用在类方法上
1、property
property装饰器用于类中的函数,使得我们可以像访问属性一样获取一个函数的返回值

class XiaoHong:
    first_name='明'
    last_name='小'

    @property
    def full_name(self):
        return self.last_name+self.first_name
xiaohong=XiaoHong()
print(xiaohong.full_name)

2、staticmethod
staticmethod表示被装饰得方法将会是一个静态方法,意味着该方法可以直接被调用,无需实例化,但同样意味着它没有self参数,无法访问实例化后得对象

class XiaoMing:
    @staticmethod
    def say_hello():
        print("同学你好")
XiaoMing.say_hello()
xiaoming=XiaoMing()
xiaoming.say_hello()

3、classmethod
classmethod表示被装饰得方法将会是一个类方法,意味着该方法可以直接被调用 无需实例化,同样意味着没有self参数,也无法访问实例化后得对象。相对于staticmethod得区别是它会接收一个指向类本身得cls参数

class XiaoMing:
    name='小明'
    @classmethod
    def say_hello(cls):
        print("你好,我是",cls.name)
        print(cls)
XiaoMing.say_hello()

9、wraps装饰器

一个函数不止有执行语句,还有name(函数名),doc(说明文档)等属性,装饰器会导致这些属性改变
运行下方代码,由于装饰器返回了wrapper函数替换掉了之前的say_hello函数,导致函数名,帮助文档变成了wrapper函数的了

def decorator(func):
    def wrapper(*args, **kwargs):
        """doc of wrapper"""
        print('123')
        return func(*args, **kwargs)

    return wrapper

@decorator
def say_hello():
    """doc of say hello"""
    print('同学你好')

print(say_hello.__name__)
print(say_hello.__doc__)

解决这一问题的办法是通过functools模块下的wraps装饰器

from functools import wraps

def decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """doc of wrapper"""
        print('123')
        return func(*args, **kwargs)

    return wrapper

@decorator
def say_hello():
    """doc of say hello"""
    print('同学你好')

print(say_hello.__name__)
print(say_hello.__doc__)

wrapper使用了通配符,*args代表所有的位置参数,**kwargs代表所有的关键词参数。这样就可以应对任何参数情况。
wrapper调用被装饰的函数的时候,只要原封不动的把参数再传递进去就可以
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

测试运维小猴子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值