Because a subclass instance may be used as an instance of the superclass, overriding methods should uphold the aspects of the superclass contract that relate to the Liskov Substitution Principle. Specifically, an overriding method should be callable with the same parameters as the overriden one.
The following modifications are ok:
*args). **kwargs). The following modifications are not ok:
*args). **kwargs). This rule raises an issue when the signature of an overriding method does not accept the same parameters as the overriden one. Only instance methods are considered, class methods and static methods are ignored.
class ParentClass(object):
def mymethod(self, param1):
pass
class ChildClassMore(ParentClass):
def mymethod(self, param1, param2, param3): # Noncompliant * 2.
# Remove parameter "param2" or provide a default value.
# Remove parameter "param3" or provide a default value.
pass
class ChildClassLess(ParentClass):
def mymethod(self): # Noncompliant. Add missing parameter "param1".
pass
class ChildClassReordered(ParentClass):
def mymethod(self, inserted, param1): # Noncompliant
# Remove parameters "inserted" or provide a default value.
pass
class ParentClass(object):
def mymethod(self, param1):
pass
class ChildClassMore(ParentClass):
def mymethod(self, param1, param2=None, param3=None):
pass
class ChildClassLess(ParentClass):
def mymethod(self, param1=None):
pass
class ChildClassReordered(ParentClass):
def mymethod(self, param1, inserted=None):
pass
In theory renaming parameters also breaks Liskov Substitution Principle. Arguments can't be passed via keyword arguments anymore. However, as PEP-570 says, it is common to rename parameters when it improves code readability and when arguments are always passed by position.
"Positional-Only Parameters" were introduced in python 3.8 to solve this problem. As most programs will need to support older versions of python, this rule won't raise an issue on renamed parameters.
class ParentClass(object):
def mymethod(self, param1):
pass
class ChildClassRenamed(ParentClass):
def mymethod(self, renamed): # No issue but this is suspicious. Rename this parameter as "param1" or use positional only arguments if possible.
pass