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!