是否可以在 class 中创建装饰器?
Is it possible to create a decorator inside a class?
或者您可以想出一个替代解决方案来解决我正在尝试做的事情。基本上我有一个 class 和一堆函数,我想将它们包装在 try/except 块中以拦截 KeyboardInterrupt 错误,因为我有一个函数可以整齐地清理我的每一个功能。
与其在每个函数中放置巨大的 try catch 块,我想我可以创建一个装饰器来做到这一点,但我 运行 遇到了一些问题。到目前为止我有这样的东西
class MyClass:
def catch_interrupt(self, func):
def catcher():
try:
func()
except KeyboardInterrupt:
self.End()
return catcher
@catch_interrupt
def my_func(self):
# Start a long process that might need to be interrupted
def End(self):
# Cleans up things
sys.exit()
当我 运行 这是我收到错误时的问题
TypeError: catch_interrupt() takes exactly 2 arguments (1 given)
这可能吗?有没有更好的方法或者我真的应该在每个函数内部放置 try/except 块?
我不确定您是否可以在您建议的性质中的 class 中使用装饰器。我认为这与装饰器本身的目的是违反直觉的(可以说是 hack)。
try-except 块有什么问题?您已经将所有清理代码放在一个函数中,因此遵守 DRY 原则。装饰器 and/or 包装器只会限制错误处理的灵活性,通过修复 try-except 语句包装整个函数,而不会提供任何实际的附加好处。
确实可以在 class 中创建装饰器,但您的实现有问题:
首先,catch_interrupt()
不能带self
。
@catch_interrupt
def my_func(self):
# Start a long process that might need to be interrupted
等同于
def my_func(self):
# Start a long process that might need to be interrupted
my_func = catch_interrupt(my_func)
显然这不允许 self
.
其次,您从装饰器 return 得到的内部包装函数至少需要将 self
作为参数并将其传递给 func
,作为您将要使用的函数装饰期望 self
作为他们的第一个参数。
您可能还想调用您的内部装饰器 _catch_interrupt
来暗示它是供内部使用的。这不会阻止任何人调用它,但这是一个很好的做法,因为如果在 class 的实例上调用该行为将是不正确的(例如 MyClass().catch_interrupt()
将尝试装饰 MyClass
实例本身,你可能不想要)。
不过,我的建议是改为实施 context manager 并让它执行您的清理工作。对于你只是包含一组语句的情况,这更符合 Pythonic,如果你正确地实现它,你实际上也可以将它用作装饰器。
或者您可以想出一个替代解决方案来解决我正在尝试做的事情。基本上我有一个 class 和一堆函数,我想将它们包装在 try/except 块中以拦截 KeyboardInterrupt 错误,因为我有一个函数可以整齐地清理我的每一个功能。
与其在每个函数中放置巨大的 try catch 块,我想我可以创建一个装饰器来做到这一点,但我 运行 遇到了一些问题。到目前为止我有这样的东西
class MyClass:
def catch_interrupt(self, func):
def catcher():
try:
func()
except KeyboardInterrupt:
self.End()
return catcher
@catch_interrupt
def my_func(self):
# Start a long process that might need to be interrupted
def End(self):
# Cleans up things
sys.exit()
当我 运行 这是我收到错误时的问题
TypeError: catch_interrupt() takes exactly 2 arguments (1 given)
这可能吗?有没有更好的方法或者我真的应该在每个函数内部放置 try/except 块?
我不确定您是否可以在您建议的性质中的 class 中使用装饰器。我认为这与装饰器本身的目的是违反直觉的(可以说是 hack)。
try-except 块有什么问题?您已经将所有清理代码放在一个函数中,因此遵守 DRY 原则。装饰器 and/or 包装器只会限制错误处理的灵活性,通过修复 try-except 语句包装整个函数,而不会提供任何实际的附加好处。
确实可以在 class 中创建装饰器,但您的实现有问题:
首先,catch_interrupt()
不能带self
。
@catch_interrupt
def my_func(self):
# Start a long process that might need to be interrupted
等同于
def my_func(self):
# Start a long process that might need to be interrupted
my_func = catch_interrupt(my_func)
显然这不允许 self
.
其次,您从装饰器 return 得到的内部包装函数至少需要将 self
作为参数并将其传递给 func
,作为您将要使用的函数装饰期望 self
作为他们的第一个参数。
您可能还想调用您的内部装饰器 _catch_interrupt
来暗示它是供内部使用的。这不会阻止任何人调用它,但这是一个很好的做法,因为如果在 class 的实例上调用该行为将是不正确的(例如 MyClass().catch_interrupt()
将尝试装饰 MyClass
实例本身,你可能不想要)。
不过,我的建议是改为实施 context manager 并让它执行您的清理工作。对于你只是包含一组语句的情况,这更符合 Pythonic,如果你正确地实现它,你实际上也可以将它用作装饰器。