开发者社区> 问答> 正文

为类和静态方法提供装饰器

你想给类或静态方法提供装饰器。

展开
收起
哦哦喔 2020-04-17 16:16:48 1157 0
2 条回答
写回答
取消 提交回答
  • 有点尴尬唉 你要寻找的东西已经被吃掉啦!

    如果你把装饰器的顺序写错了就会出错。例如,假设你像下面这样写:

    class Spam: @timethis @staticmethod def static_method(n): print(n) while n > 0: n -= 1

    那么你调用这个静态方法时就会报错:

    Spam.static_method(1000000) Traceback (most recent call last): File " ", line 1, in File "timethis.py", line 6, in wrapper start = time.time() TypeError: 'staticmethod' object is not callable

    问题在于 @classmethod 和 @staticmethod 实际上并不会创建可直接调用的对象, 而是创建特殊的描述器对象(参考8.9小节)。因此当你试着在其他装饰器中将它们当做函数来使用时就会出错。 确保这种装饰器出现在装饰器链中的第一个位置可以修复这个问题。

    当我们在抽象基类中定义类方法和静态方法(参考8.12小节)时,这里讲到的知识就很有用了。 例如,如果你想定义一个抽象类方法,可以使用类似下面的代码:

    from abc import ABCMeta, abstractmethod class A(metaclass=ABCMeta): @classmethod @abstractmethod def method(cls): pass

    在这段代码中,@classmethod 跟 @abstractmethod 两者的顺序是有讲究的,如果你调换它们的顺序就会出错。

    2020-04-17 17:41:37
    赞同 展开评论 打赏
  • 给类或静态方法提供装饰器是很简单的,不过要确保装饰器在 @classmethod 或 @staticmethod 之前。例如:
    
    import time
    from functools import wraps
    
    # A simple decorator
    def timethis(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start = time.time()
            r = func(*args, **kwargs)
            end = time.time()
            print(end-start)
            return r
        return wrapper
    
    # Class illustrating application of the decorator to different kinds of methods
    class Spam:
        @timethis
        def instance_method(self, n):
            print(self, n)
            while n > 0:
                n -= 1
    
        @classmethod
        @timethis
        def class_method(cls, n):
            print(cls, n)
            while n > 0:
                n -= 1
    
        @staticmethod
        @timethis
        def static_method(n):
            print(n)
            while n > 0:
                n -= 1
    装饰后的类和静态方法可正常工作,只不过增加了额外的计时功能:
    
    >>> s = Spam()
    >>> s.instance_method(1000000)
    <__main__.Spam object at 0x1006a6050> 1000000
    0.11817407608032227
    >>> Spam.class_method(1000000)
    <class '__main__.Spam'> 1000000
    0.11334395408630371
    >>> Spam.static_method(1000000)
    1000000
    0.11740279197692871
    >>>
    
    2020-04-17 16:16:57
    赞同 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
函数对象 立即下载
低代码开发师(初级)实战教程 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载