This rule raises an issue when a property getter, setter or deleter does not have the correct number of arguments.
Creating property accessors and mutators is quite common in Object-Oriented Programming. Python provides two main ways of implementing getters,
setters and deleters; either with the @property decorator, or with the property function.
class WithPropertyDecorator(object):
@property
def foo(self)
return self._foo
@foo.setter
def foo(self, value):
self._foo = value
@foo.deleter
def foo(self):
del self._foo
class WithPropertyMethod(object):
def get_foo(self):
return self._foo
def set_foo(self, value):
self._foo = value
def del_foo(self):
del self._foo
foo = property(get_foo, set_foo, del_foo, "'foo' property.")
The following program illustrates how using the built-in operations will call the custom methods defined above.
with_decorator = WithPropertyDecorator() with_decorator.foo = 1 # the method defined under @foo.setter will be called. some_var = with_decorator.foo # the method defined under @foo.getter will be called. del with_decorator.foo # the method defined under @foo.deleter will be called. with_method = WithPropertyMethod() with_method.foo = 1 # the method set_foo will be called. some_var = with_method.foo # the method get_foo will be called. del with_method.foo # the method del_foo will be called.
Defining a property this way allows for flexibility when refactoring the implementation of the getters, setters and deleters method, as all the
accesses and modifications are done through the Python built-in operators (=,.) and keyword (del).
Property getter, setter and deleter methods are called by the Python interpreter with a specific number of arguments:
Adding any other parameters, or removing these mandatory parameters will throw a TypeError exception at runtime when trying to access
or modify the property.
Make sure to specify the correct number of argument for each setter, getter and deleter methods.
class A:
@property
def foo(self, unexpected, unexpected2): # Noncompliant: too many parameters.
return self._foo
@foo.setter
def foo(self): # Noncompliant: a parameter is missing.
self._foo = 42
@foo.deleter
def foo(self, unexpected): # Noncompliant: too many parameters.
del self._foo
class B:
def get_foo(self, unexpected): # Noncompliant: too many parameters.
return self._foo
def set_foo(self, value, unexpected): # Noncompliant: too many parameters.
self._foo = value
def del_foo(self, unexpected): # Noncompliant: too many parameters.
del self._foo
foo = property(get_foo, set_foo, del_foo, "'foo' property.")
class A:
@property
def foo(self):
return self._foo
@foo.setter
def foo(self, value):
self._foo = value
@foo.deleter
def foo(self):
del self._foo
class B:
def get_foo(self):
return self._foo
def set_foo(self, value):
self._foo = value
def del_foo(self):
del self._foo
foo = property(get_foo, set_foo, del_foo, "'foo' property.")