简体   繁体   English

python3装饰器中方法调用中参数“self”没有值

[英]No value for argument 'self' in method call in python3 decorator

I'm trying to use decorator into class and get an error in pylint on line我正在尝试在课堂上使用装饰器,但在线 pylint 中出现错误

@start_test_min_pg(min_version_pg="9.5") @start_test_min_pg(min_version_pg="9.5")

No value for argument 'self' in method call方法调用中参数“self”没有值

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

The way that you've written your decorator, it needs to be called on an instance of your class to work properly.按照您编写装饰器的方式,需要在类的实例上调用它才能正常工作。 That is, you'd need to be applying it with:也就是说,你需要应用它:

obj = TestsUnloggedTabled(...)

@obj.start_test_min_pg(min_version_pg="9.5")
def foo():
    pass

This obviously can't work when you're applying it to another method in the same class, since you can't create an instance until the class definition ends.当您将它应用于同一类中的另一个方法时,这显然不起作用,因为在类定义结束之前您无法创建实例。 So you clearly don't want to be calling the decorator as a method, which means you should not have self as one of its arguments.因此,您显然不想将装饰器作为方法调用,这意味着您不应该将self作为其参数之一。

But you do need self in the implementation of your code later.但是您在以后的代码实现中确实需要self Where do you get it?你从哪里得到它? Well, the wrapper_repeat function is what is going to be called on the actual instance, once the class is defined.好吧,一旦定义了类,将在实际实例上调用wrapper_repeat函数。 So its first argument will be that instance, and you can name it self rather than letting it get collected with the other positional arguments in args .因此,它的第一个参数将是该实例,您可以将其命名为self而不是让它与args的其他位置参数一起收集。 You do need to remember to pass it along when you call the original function.您确实需要记住在调用原始函数时传递它。

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, *args, **kwargs)                # and pass it along
               return value
       return wrapper_repeat
   return decorator_repeat

Note that I fixed the indentation level of the last two lines of this code, the version in your question won't work correctly (since the decorator factory will return None ).请注意,我修复了此代码最后两行的缩进级别,您问题中的版本将无法正常工作(因为装饰器工厂将返回None )。 I'm guessing that may be an artifact of copying the code into Stack Overflow, not something that's actually wrong in your real code.我猜这可能是将代码复制到 Stack Overflow 的人工产物,而不是您的真实代码中实际上有问题的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM