arguments-differ / W0221#

Message emitted:

%s %s %r method

Description:

Used when a method has a different number of arguments than in the implemented interface or in an overridden method. Extra arguments with default values are ignored.

Problematic code:

class Drink:
    def mix(self, fluid_one, fluid_two):
        return fluid_one + fluid_two


class Cocktail(Drink):
    def mix(self, fluid_one, fluid_two, alcoholic_fluid):  # [arguments-differ]
        return fluid_one + fluid_two + alcoholic_fluid

Correct code:

add_option_in_base_class.py:

"""
Here we assume that drink and cocktail are the same thing and should actually
inherit from each over. We also assume that 'Drink' are 'Cocktail' without
alcohol (we added the alcohol option in the base class).

This permit to not have to modify the cocktails calls downstream but the case where
an alcohol is mixed in a soft drink will need to be handled.
"""


class Drink:
    def mix(self, fluid_one, fluid_two, alcoholic_fluid=None):
        # if alcoholic_fluid is not None:
        #     raise Exception(f"This soft drink has {alcoholic_fluid} in it !")
        return fluid_one + fluid_two


class Cocktail(Drink):
    def mix(self, fluid_one, fluid_two, alcoholic_fluid):
        return fluid_one + fluid_two + alcoholic_fluid

default_value.py:

"""
Here we assume that drink and cocktail are the same thing and should actually
inherit from each over. We also assume that any Cocktail can be treated like
a Drink (if you add beer to it).

This permit to not have to modify the calls downstream and causes the least
amount of disturbance at the cost of making cocktails beer-based implicitly.
"""


class Drink:
    def mix(self, fluid_one, fluid_two):
        return fluid_one + fluid_two


class Cocktail(Drink):
    def mix(self, fluid_one, fluid_two, alcoholic_fluid="Beer"):
        return fluid_one + fluid_two + alcoholic_fluid

no_inheritance.py:

"""
Here we assume that 'Drink' and 'Cocktail' are different things and should
not be treated together like if they were the same thing.

This will force some downstream changes and force the API user to make a
conscious decision about the alcoholic content of its drink when using the
API. For example, it's impossible to create a mojito with beer without
explicitly wanting to, or to add an alcohol to a soft-drink.
"""


class Drink:
    def mix(self, fluid_one, fluid_two):
        return fluid_one + fluid_two


class Cocktail:
    def mix(self, fluid_one, fluid_two, alcoholic_fluid):
        return fluid_one + fluid_two + alcoholic_fluid

Additional details:

argument-differ denotes an issue with the Liskov Substitution Principle. This means that the code in question violates an important design principle which does not have one single solution. We recommend to search online for the best solution in your case.

To give some examples of potential solutions:

  • Add the argument to the parent class

  • Remove the inheritance completely

  • Add default arguments to the child class

Related links:

Created by the classes checker.