问题描述
我正在尝试在类中使用装饰器,并在在线上得到pylint错误
@start_test_min_pg(min_version_pg =“ 9.5”)
class TestsUnloggedTabled(BaseTester):
some code
def get_pg_version(self):
pg_temp = Postgres(self.host,self.port,self.username,self.password,"postgres")
current_pg_version = pg_temp.query("show server_version")[0][0].split(" ")[0]
print('PG version is: ' + current_pg_version)
return current_pg_version
def start_test_min_pg(self,min_version_pg):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args,**kwargs):
if LooseVersion(self.get_pg_version()) > LooseVersion(min_version_pg):
value = func(*args,**kwargs)
return value
return wrapper_repeat
return decorator_repeat
@start_test_min_pg(min_version_pg="9.5")
def test_schema_hashing(self):
do something
解决方法
编写装饰器的方式,需要在类的实例上调用它,以使其正常工作。也就是说,您需要将其应用于:
obj = TestsUnloggedTabled(...)
@obj.start_test_min_pg(min_version_pg="9.5")
def foo():
pass
当您将其应用于同一类中的另一个方法时,这显然不起作用,因为在类定义结束之前您无法创建实例。因此,您显然不希望将装饰器作为一种方法来调用,这意味着您不应该将self
作为其参数之一。
但是您要做在以后的代码实现中需要self
。你从哪里得到的?好了,一旦定义了类,wrapper_repeat
函数将在实际实例上调用。因此,它的第一个参数将是该实例,您可以将其命名为self
,而不是让它与args
中的其他位置参数一起被收集。您确实需要记住在调用原始函数时将其传递。
def start_test_min_pg(min_version_pg): # no self here
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(self,*args,**kwargs): # put it here instead
if LooseVersion(self.get_pg_version()) > LooseVersion(min_version_pg):
value = func(self,**kwargs) # and pass it along
return value
return wrapper_repeat
return decorator_repeat
请注意,我已修复了此代码后两行的缩进级别,因此您问题中的版本无法正常工作(因为装饰器工厂将返回None
)。我猜这可能是将代码复制到Stack Overflow中的产物,而不是您的实际代码中确实存在的错误。