ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python中的装饰器decorator(中)

2022-06-13 21:33:26  阅读:205  来源: 互联网

标签:repeat return name python decorator func kwargs 装饰 def


在上文中,我们讨论了用于修饰function的装饰器,现在我们来看用于修饰class的装饰器。首先来看一个例子,其中使用了built-in的@property @classmethod @staticmethod。@property常用于设置setter和getter。

class Student:
    
    def __init__(self, name,id):
        self._name = name
        self._id = id

    @property
    def id(self):
        return self._id

    @property
    def name(self):
        return self._name
    
    @name.setter
    def name(self, value):
        if value.isalpha():
            self._name = value

    @classmethod
    def tom(cls):
        return Student("tom",0)

    @staticmethod
    def identity():
        return "student"

在使用时,如下所示调用property修饰的方法。

>>> jack = Student("jack",1)
>>> jack.name
'jack'
>>> jack.id
1
>>> jack.name = "Jack Tony"
>>> jack.name
'jack'
>>> jack.id=2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

@classmethod vs @static method
1.class method第一个参数为cls,且能够获取类内部状态,通常作为一个工厂方法,返回这个类的一个对象。
2.static method仅仅为一个工具方法,不能获得类内部状态,只根据参数决定行为。

修饰类中的方法和修饰一个函数时一样的,自己定义的装饰器也可使用。另一种方式是装饰整个类

修饰整个类

我们在上文为函数写的装饰器都可以作用到类上,不过实际上等同于其作用到了类的__init__方法上。

多个decorator

函数有多个decorator,会按顺序执行。如下:

def do_twice(func):
    def do_twice_wrapper(*args,**kwargs):
        func(*args,**kwargs)
        
        return func(*args,**kwargs)
    return do_twice_wrapper
def debug(func):
    def debug_wrapper(*args,**kwargs):
        args_repr = [repr(a) for a in args]
        kwargs_repr = [f"{k}={v!r}"for k,v in kwargs.items() ]
        signature = ",".join(args_repr+kwargs_repr)
        print(f"calling {func.__name__}({signature})")
        value = func(*args,**kwargs)
        print(f"{func.__name__} returned {value}")
        return value

    return debug_wrapper
	
@do_twice
@debug
def greet(name):
    print(f"hello {name}")
greet("tom")

# 先@debug再@do_twice
calling greet('tom')
hello tom
greet returned None
calling greet('tom')
hello tom
greet returned None

使用带参数的decorator

比如我们要将@do_twice扩展为执行某一函数任意次数。

import functools

def repeat(num_times):
    def decorator_repeat(func):
        @functools.wraps(func)
        def wrapper_repeat(*args,**kwargs):
            for _ in range(num_times-1):
                func(*args,**kwargs)
            return func(*args,**kwargs)
        return wrapper_repeat
    return decorator_repeat
     
@repeat(num_times=4)
def greet(name):
    print(f"hello {name}")

改进装饰器

我们可以改进装饰器,使其既可以接受参数,也可以不接受

def repeat(_func=None,*,num_times=2):
    def decorator_repeat(func):
        @functools.wraps(func)
        def wrapper_repeat(*args,**kwargs):
            for _ in range(num_times-1):
                func(*args,**kwargs)
            return func(*args,**kwargs)
        return wrapper_repeat
    if _func is None:
        return decorator_repeat
    else:
        return decorator_repeat(_func)       
@repeat
def greet(name):
    print(f"hello {name}")
#等同于,repeat参数中,_func有值	
greet = repeat(greet)

@repeat(num_times=4)
def greet(name):
    print(f"hello {name}")
#等同于,repeat参数中,作为positional arguments或keywords arguments的_func没有值
tmp = repeat(num_times=4)
@tmp
def greet(name):
    print(f"hello {name}")
	

参考

标签:repeat,return,name,python,decorator,func,kwargs,装饰,def
来源: https://www.cnblogs.com/pitaya01/p/16372374.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有