I'm using a decorator with parameters to do something with an instance attribute (self.x in this example, if track_bool is true). However when running I get the "parameter 'self' unfilled" error when calling b.do(). From what I understand this error is supposed to appear when calling an instance method before instantiating an object, so I don't understand why it appears in this case when I've used b=B(). Is this something to do with the fact I'm using decorators ? Help please !
Edit: The code does run, but I would like to understand the error so that it doesn't risk breaking anything when running with the rest of my code.
# make decorator
def incrementor(track_bool):
def wrapper(f):
def wrapped_f(self, *args, **kwargs):
if track_bool:
self.x = 1 # do something with self.x
print('increment')
return f(self, *args, **kwargs)
return wrapped_f
return wrapper
class B:
def __init__(self):
self.x = 0
@incrementor(track_bool=True)
def do(self):
print("this is a function with x=", self.x)
b = B() # instantiate
b.do() # call decorated method
Here is the image of the error: PyCharm IDE message
CodePudding user response:
Ok, this is PyCharm being a tiny bit too eager. You should submit a bug report for this because your code is actually working just fine and you don't want to have to go round suppressing all calls to decorated methods.
Here is a work-around. You can change the decorator to not have an explicit self
parameter:
def incrementor(track_bool):
def wrapper(f):
def wrapped_f(*args, **kwargs):
if track_bool:
self = args[0]
self.x = 1 # do something with self.x
print('increment')
return f(*args, **kwargs)
return wrapped_f
return wrapper
Note how you can still get hold of self
because it is guaranteed to be the first element of args
.