Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Object-Oriented Python Inheritance Multiple Superclasses

Anthony Grodowski
Anthony Grodowski
4,902 Points

Problem with name

I can't quite get why we need to set name keyword argument in order to run the code. Why do we put name="" in the init? TIA

1 Answer

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,457 Points

Good question. Keep in mind that a supplied positional argument would be applied to the first available parameter, be it positional or keyword parameter!

With the inclusion of Agile and Sneaky, the first positional argument "Kenneth" would be applied to the agile parameter:

# Note: `name=foo` added to pass `if not name:` test
>>> thieves.Thief("Kenneth", sneaky=True, name="foo").__dict__
{'name': 'foo', 'sneaky': True, 'agile': 'Kenneth'}

The attribute agile gets assigned "Kenneth"!

Why do we put name="" in the __init__? By supplying a default value for the parameter name it covers the case where the name might have been swallowed up by a previous positional assignment. If all the parameters are provided, keyword use isn't necessary. But if one parameter isn't filled, then name would become the default empty string and the check in Character would raise the error.

>>> thieves.Thief(True, True, "Kenneth").__dict__
{'name': 'Kenneth', 'sneaky': True, 'agile': True}
>>> thieves.Thief(True, "Kenneth").__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/chris/devel/Treehouse/Thief/attributes.py", line 19, in __init__
    super().__init__(*args, **kwargs)
  File "/home/chris/devel/Treehouse/Thief/attributes.py", line 8, in __init__
    super().__init__(*args, **kwargs)
  File "/home/chris/devel/Treehouse/Thief/characters.py", line 4, in __init__
    raise ValueError("'name' is required")
ValueError: 'name' is required

Post back if you need more help. Good luck!!

Anthony Grodowski
Anthony Grodowski
4,902 Points

Thnak you! That cleared almost everything!

"With the inclusion of Agile and Sneaky, the first positional argument "Kenneth" would be applied to the agile parameter" - but if in Agile there would be, for example, agile = "Able To Dodge", then "Kenneth" parameter couldn't overwrite it, right? True, False and None could be eaisly overwritten by "Kenneth", but explicit keyword argument can't.

Chris Freeman
Chris Freeman
Treehouse Moderator 68,457 Points

Again, good question!

Important point: a function only has parameters, some may have default values define, others may not.

Having a default value for a parameter does not protect it being assigned to a positional argument.

In my answer above, agile is assigned β€œKenneth” even though it has a default value True

Keywords only come into play if the argument in the statement calling the function has a keyword with the argument. In this case the argument will only be applied to the parameter of the same name.

If β€œKenneth” had been used as an argument along with agile=True then an error would be raised saying Error: agile already assign an argument`

# Note: `name=foo` added to pass `if not name:` test
>>> thieves.Thief("Kenneth", agile=True, name="foo").__dict__
TypeError: Thief() got multiple values for argument β€˜agile’