【问题标题】:Python decorator class with function counter variable具有函数计数器变量的 Python 装饰器类
【发布时间】:2014-03-18 20:48:28
【问题描述】:

我在 Python 中有一个类,我需要将其用作装饰器类,但我想在调用它时计算一些东西:

class SomeClass:

    counter = 0

    @staticmethod
    def some_function(a):
        """
        -----------------------
        Does something
        -----------------------
        """
        SomeClass.counter += 1
        a = a * a
        return a

调用后:

a = new_var.some_function(a) 

然后如何从装饰器类中获取计数器值?

【问题讨论】:

  • 我认为你的意思是变量而不是常量,因为常量不应该改变。
  • SomeClass.constant?
  • 静态方法不将 self 作为参数。
  • 是什么让你的班级成为装饰者?

标签: python class object decorator


【解决方案1】:

您向我们展示的类不是装饰器——它只是一个类。访问柜台就像

SomeClass.counter
# current counter value

让你的班级成为真正的装饰者并不难——不过,我将把它重命名为 Counter

class Counter:
    """
    Count the number of calls made to the wrapped function.
    """
    def __init__(self, func):
        self.counter = 0
        self.func = func
    def __call__(self, *args, **kwds):
        self.counter += 1
        return self.func(*args, **kwds)

@Counter
def square(n):
    return n * n

并在使用中:

square(3)
# 9
square(7)
# 41
square(11)
# 121

square.counter
# 3

注意:这是一个非常简单的装饰器,一个副作用是包装函数的签名丢失了。

解包的签名:

Help on function square in module __main__:
square(n)

封装的签名:

Help on instance of Counter in module __main__:
class Counter
 |  Count the number of calls made to the wrapped function.
 |  
 |  Methods defined here:
 |  
 |  __call__(self, *args, **kwds)
 |  
 |  __init__(self, func)

【讨论】:

    【解决方案2】:

    我想这取决于您要如何计算。例如:

    >>> class A(object):
    >>>     pass
    >>> ...
    >>> def foo(obj):
    >>>     def inner(*args, **kwargs):
    >>>         counter += 1
    >>>         print "times called: %d" % counter
    >>>     counter = 0
    >>>     return inner
    
    >>> Bar = A()
    >>> Bar.eggs = foo(Bar)
    >>> Bar.foo()
    times called: 1
    >>> Bar.foo()
    times called: 2
    >>> Spam = A()
    >>> Spam.eggs = foo(Spam)
    >>> Spam.eggs()
    times called: 1
    

    这是可行的,因为包装器将随身携带其环境,这意味着counter 在包装时位于an_object.foo 的任何给定实例的范围内。尽管它可能不像您需要的那样内省。 或者,您的意思是计算实际调用obj.foo 的总次数?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-24
      • 1970-01-01
      • 1970-01-01
      • 2018-04-07
      • 2018-08-16
      • 2021-06-24
      • 2012-11-24
      • 2014-07-21
      相关资源
      最近更新 更多