Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在类中使用装饰器_Python_Oop_Decorator - Fatal编程技术网

Python 在类中使用装饰器

Python 在类中使用装饰器,python,oop,decorator,Python,Oop,Decorator,我正在尝试在我的应用程序中实现一个简单的日志功能 class messages(object): # Implement decorator here def on(self): def wrapper(): # Do something here return wrapper def off(self): def wrapper(): # Do something her

我正在尝试在我的应用程序中实现一个简单的日志功能

class messages(object):

    # Implement decorator here
    def on(self):
        def wrapper():
            # Do something here
        return wrapper

    def off(self):
        def wrapper():
            # Do something here
        return wrapper


class website(object):

    @messages.on #This line can be switched on/off
    def login(self):
        # Do a whole bunch of stuff here
        self.response = "[+] Login Succeeded!"

website = website()
website.login() # prints self.response based on @messages.on/off

但我不确定我需要在我的装饰师那里申请什么。我尝试过创建实例和添加参数,但大部分都收到TypeError。我对装潢师还不太熟悉。任何帮助都将不胜感激,我希望下次记住这一点。

以下是您可以使用的装饰器示例:

class Utilities:

    @staticmethod
    def add_logger(func):
        def wrapped_func(*args, **kwargs):
            # Sample logic, feel free to update this
            try:
                func_response = func(*args, **kwargs)
            except:
                print 'I am error handled by logger'
                func_response = None
            return func_response
        return wrapped_func
现在让我们定义您的类:

class Dog(object):

    @Utilities.add_logger 
    def bark(self):
        print 'In bark'

    @Utilities.add_logger 
    def my_error_function(self):
        print 'In my_error_function'
        raise Exception  # <--- Raises Exception
注意:您不应该在此处创建
类来存储实用程序函数。创建一个单独的实用程序文件,并在那里编写这样的函数

如果没有类,您的decorator应该是(比如在utility.py中):

要使用它,只需执行以下操作:

import utility

class Dog(object):

    @utility.add_logger
    def bark(self):
        print 'In bark'
  • 如果您只想让狗吠叫(如示例中所示),则无需启用装饰器

    class Dog(object):
        def __init__(self):
            self.sound = "Woof!"
    
        def bark(self):
            return self.sound
    
  • 如果您想为类中的某些函数启用日志记录,下面是一段代码,可以在注释中进行解释

    from functools import wraps
    
    class Utilities(object):
    
        @staticmethod  # no default first argument in logger function
        def logger(f):  # accepts a function
            @wraps(f)  # good practice https://docs.python.org/2/library/functools.html#functools.wraps
            def wrapper(self, *args, **kwargs):  # explicit self, which means this decorator better be used inside classes only
                print("Before:", self.sound)
                result = f(self, *args, **kwargs)
                print("After:", self.sound)
                return result
            return wrapper
    
    
    class Dog(object):
        def __init__(self):
            self.sound = "Woof!"
    
        @Utilities.logger
        def run(self):
            """Perform running movement"""
            print("Running")
    
  • 例如:

    >>> dog = Dog()
    >>> dog.run()
    Before: Woof!
    Running
    After: Woof!
    

    尽管毕竟没有必要在
    实用程序
    类中存储decorators功能,但最好有一个名为
    utils
    的单独模块(文件),并将decorator作为一个独立的函数放在那里

    您可能想引用@Hussain:这在这里并不适用;他们没有使用来自同一个类主体的函数。你的方法没有任何意义。首先,
    logger
    中的
    self
    引用了您没有的
    实用程序
    实例-您是说它是一个
    @staticmethod
    ?为什么它在类中(这不是Java)?其次,将它绑定到
    .sound
    属性几乎不可能重用。为什么不让
    bark
    始终返回
    'woof'
    ,然后让包装器在调用其包装的方法时打印它返回的任何内容?当你呼叫狗吠时,为什么要打印
    ?最后,不要用新实例
    Dog
    来隐藏类
    Dog
    ;按照惯例,
    dog=dog()
    @MartijnPieters我想展示@Hussain:是的,但这不适用于这里。我想使用这个代码,谢谢你,只是我不明白它是如何工作的,所以我会做更多的研究。最初,我想在代码中的每个方法之后添加try-except语句,但我想使用一个装饰器来几乎“切换”这个日志功能。我认为decorators将是一个很好的用例。我已经更新了代码。谢谢你的帮助。你会推荐同样的建议吗?装饰器是为多个函数添加相同逻辑的好方法,是的。只需在“before”和“after”的位置插入所需代码。很高兴它对您有效,如果有帮助,您可以将答案标记为已接受:)请查看更新的代码,谢谢。告诉我这是否仍然适用。感谢您的意见!对这是一个装潢师的骨架。更改
    wrapped_func
    中的逻辑,以实现您想要实现的任何目标
    from functools import wraps
    
    class Utilities(object):
    
        @staticmethod  # no default first argument in logger function
        def logger(f):  # accepts a function
            @wraps(f)  # good practice https://docs.python.org/2/library/functools.html#functools.wraps
            def wrapper(self, *args, **kwargs):  # explicit self, which means this decorator better be used inside classes only
                print("Before:", self.sound)
                result = f(self, *args, **kwargs)
                print("After:", self.sound)
                return result
            return wrapper
    
    
    class Dog(object):
        def __init__(self):
            self.sound = "Woof!"
    
        @Utilities.logger
        def run(self):
            """Perform running movement"""
            print("Running")
    
    >>> dog = Dog()
    >>> dog.run()
    Before: Woof!
    Running
    After: Woof!