我想在一个类中定义一个装饰器。我不想将其定义为单独的独立函数,因为此装饰器专门用于此类,所以我想将相关方法保持在一起。
此装饰器的目的是检查某些先决条件,尤其是由成员变量保存的数据库连接,SSH连接等仍然可用。如果没有,则装饰函数将不会被调用,并且将完成一些错误报告和清理工作。
我制作了以下测试类来测试它是否有效,并且代码运行良好。但是我发现PyCharm对这段代码显示警告。所以我想知道这是否意味着我的代码不是Python语言,或者PyCharm不够聪明,并错误地发出了此警告?
如果我的代码不是Pythonic,如何更改? 如果是PyCharm的错误,我和我的团队应如何配置PyCharm以使其在保留大多数其他皮棉检查的同时专门忽略这种警告?
class TestClass:
def __init__(self):
self.flag = True
def dec(func):
def wrapper(self, *args, **kwargs):
if not self.flag:
print("Won't run!")
return empty_fun(self, *args, **kwargs)
return func(self, *args, **kwargs)
def empty_fun(*args, **kwargs):
return None
return wrapper
@dec
def foo(self):
print("foo")
@dec
def bar(self, msg, more, *args, **kwargs):
print("message: %s" % msg)
print("more %s:" % more)
for item in args:
print("other item: %s" % item)
name = kwargs.get('name')
age = kwargs.get('age')
print('name: %s' % name)
print('age: %s' % age)
def main():
t = TestClass()
t.foo()
print('-'*10)
t.bar("abc", 'def', 'hij', 'klm', name='Tom', age=20)
if __name__ == '__main__':
main()
这是PyCharm报告的皮棉警告:
答案 0 :(得分:3)
您的代码在技术上是正确的(因为它可以按预期工作),但需要注意的是,dec
将成为TestClass
的方法,并且如果这样调用将被破坏。为避免这种情况,您至少应将其设置为staticmethod
。
wrt / pythonicity,在不需要此装饰器时,将其作为类的一部分确实是不Python的。它仅适用于此类的事实并不是使其成为该类成员的原因,更不用说使其成为公共API的一部分了。
您可能可以在注释中添加linter提示以使其静音,但是我个人只是从类中提取此装饰器,将其设置为私有,并记录它仅应与该类一起使用。
作为旁注:我假设您的empty_func
是“错误报告和清理工作”的占位符-否则它根本就没用-但确实需要在装饰器中定义它吗?
答案 1 :(得分:2)
从Python decorator as a staticmethod开始,不鼓励在类中放置装饰器。
想想看,Python提供了这种很好的划分方式,称为 modules 。您是否考虑过将与此类相关的所有代码放在一个模块中,而其他代码放在其他模块中?
我强烈建议将装饰器移至模块作用域-它似乎不属于类内部。如果您想将其保留在类中,请不要将其设置为
staticmethod
,而只需将其del
放在类正文的末尾即可–不能在类外使用在这种情况下。