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 (retired) Inheritance Instance Methods

INIT function allows user to override Weapon logic

Kenneth Love

Trying to understand best practices.

The weapon selection is supposed to be controlled by the get_weapon() method, but since that input is followed by the processing of the KWARGS argument the user can bypass this logic.

Ex: Slimy = Character(weapon="hammer')

In this case the selection logic will always be overridden by the value set in the instantiation call.

To best handle this should we check for the specific key and excluding any change that field:

  def __init__(self, **kwargs):
    self.name = input("Name: ")
    self.weapon = self.get_weapon()

    for key, value in kwargs.items():
      if key != 'weapon':
        setattr(self, key, value)

Appreciate all your work in this training.

2 Answers

Kenneth Love
STAFF
Kenneth Love
Treehouse Guest Teacher

You typically won't assign explicit attributes from **kwargs, though. Consider this:

def __init__(self, name, weapon, **kwargs):
    self.name = name
    self.weapon = weapon

    for key, value in kwargs.items():
        setattr(self, key, value)

There's no way for **kwargs to have name or weapon in it.

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,427 Points

Yes, that's the basic idea. If you wish more restrictive access to setting the weapon attribute, the filtering out the case works. Restricts can be define to be exclusionary or inclusive:

ALLOWED_ATTRIBUTES = ["sound",  "max_hit_points", "min_hit_points"]

def __init__(self, **kwargs):
    self.name = input("Name: ")
    self.weapon = self.get_weapon()

    for key, value in kwargs.items():
      if key in ALLOWED_ATTRIBUTES:
        setattr(self, key, value)

I've found using **kwargs can make testing harder and error injection harder to prevent. It does have it's uses when you need to accept an argument that is used by the parent class init through super().__init__(). YMMV.