简体   繁体   English

如何在 python 中创建装饰器 class 的不同实例

[英]How to create different instances of decorator class in python

I am currently trying to implement a decorator class to keep track of function calls within the waiter class that I have 2 instances of.我目前正在尝试实现一个装饰器 class 来跟踪我有 2 个实例的服务员 class 中的 function 调用。 I want the 2 waiter instances to have separate instances of the decorator class to keep track of calls on each of them, is this possible?我希望 2 个服务员实例有单独的装饰器实例 class 来跟踪每个服务员的调用,这可能吗?

Code:代码:

from functools import update_wrapper
import time

class decorater():
    """
    counts the number of calls and passes it into function
    """
    def __init__(self,func):
        self.func = func
        self.num_calls = 0
        update_wrapper(self, func)

    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        result = self.func(self.num_calls, *args, **kwargs) # passes num_calls in for seconds
        print(f"total runs of {self.func.__name__}: {self.num_calls}")
        return result
    
class waiter():
    """
    waits for the number of seconds passed in
    """
    @decorater
    def wait_for(seconds, var_name):
        time.sleep(seconds)
        print(f"{var_name} waited for {seconds} seconds")

waiter1 = waiter()
waiter2 = waiter()

waiter1.wait_for("waiter1")
waiter2.wait_for("waiter2")

Output: Output:

waiter1 waited for 1 seconds
total runs of wait_for: 1
waiter2 waited for 2 seconds
total runs of wait_for: 2

Desired output:所需的 output:

waiter1 waited for 1 seconds
total runs of wait_for: 1
waiter2 waited for 1 seconds
total runs of wait_for: 1

Decorators are not really supposed to be used how you are trying to use them, and because you are already creating multiple instances of the waiter class, why not just handle everything inside of each of those instances instead of using a decorator?装饰器不应该按照您尝试使用它们的方式使用,并且因为您已经创建了waiter class 的多个实例,为什么不直接处理每个实例中的所有内容而不是使用装饰器呢?

Something like this:像这样的东西:

import time


class Waiter(object):
    """
    waits for the number of seconds passed in
    """

    def __init__(self, name):
        self.name = name
        self.num_calls = 0

    def wait(self):
        self.num_calls += 1
        print(f"total runs of {self.num_calls}")

        time.sleep(self.num_calls)
        print(f"{self.name} waited for {self.num_calls} seconds")


waiter1 = Waiter("waiter1")
waiter2 = Waiter("waiter2")

waiter1.wait()
waiter2.wait()

Output: Output:

total runs of 1
waiter1 waited for 1 seconds
total runs of 1
waiter2 waited for 1 seconds

A decorator can be any callable.装饰器可以是任何可调用的。

In your code, you used the class decorator itself (and not an instance thereof) as the decorator.在您的代码中,您使用了 class decorator本身(而不是其实例)作为装饰器。 In this case, the __init__ method of the decorator class is invoked with the decorated function as an argument.在这种情况下, decorator class 的__init__方法被调用,装饰器 function 作为参数。

In order to use an instance of the class as a decorator, you would have to replace the decoration @decorator with @decorator() .为了使用 class 的实例作为装饰器,您必须将装饰@decorator替换为@decorator() That would cause the invocation of the __call__ method of a decorator instance with the decorated function as an argument.这将导致调用decorator实例的__call__方法,并将装饰的 function 作为参数。 Of course, you would have to adapt the signature of the __call__ method.当然,您必须调整__call__方法的签名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM