"Node.js Basics (2014)" was retired on February 14, 2017. You are now viewing the recommended replacement.
Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Well done!
You have completed Object-Oriented Python!
You have completed Object-Oriented Python!
Methods, like functions, are better with arguments. Let's see how to make our methods take parameters other than just the instance they're called on.
All of the same rules apply to method arguments as they do to function arguments, with the exception that the first argument has to represent the instance. You can use default values, *args, and **kwargs all you want!
Did the setattr() usage in this video catch you off-guard? Let's talk about what it is and what it's doing.
First, read the docs about it. I know documentation can sometimes be hard to read, but getting in the habit of reading it, starting there, will help you a lot in the long run.
Now, let's try an experiment. I have a class:
class Animal:
def __init__(self, **kwargs):
self.species = kwargs.get("species")
self.age = kwargs.get("age")
self.sound = kwargs.get("sound")
I'm using **kwargs here to pack any and all keyword arguments into a dictionary. And then I'll make a wolf using that class.
>>> wolf = Animal(species="Canus Lupus", age=5, sound="howl", color="gray")
>>> wolf.species
"Canus Lupus"
Great. No errors, Python's happy, I have an instance of my Animal class. In the __init__, I set three attributes: species, age, and sound. I didn't set color, though. Is it available?
>>> wolf.color
AttributeError...
No, it's not! But there weren't any errors when I created the instance. Why isn't the attribute available?
Well, because I didn't create it. Remember, Python is very explicit. If I don't do something explicitly, Python doesn't do it at all. Since I didn't assign a color attribute to self, my instance doesn't have a color attribute.
This is where setattr comes in. setattr lets me set attributes that I don't know about beforehand. I can, of course, go back and explicitly define a color attribute but what if the next user comes along and she wants a height or weight attribute? A year from now, Animal.__init__ might be hundreds of lines long with attribute declarations! And some of those attributes will only apply to a few animals!
But...if I'm clever and use setattr, I can just happily accept any and all attributes that someone gives for a particular Animal instance without having to continually update __init__.
class Animal:
def __init__(self, **kwargs):
for attribute, value in kwargs.items():
setattr(self, attribute, value)
So, since I have a handy-dandy kwargs dict due to using **kwargs in the method parameters, I can loop through its items method and pull out the two values from each iteration into attribute and value variables.
The setattr function takes three arguments: the object to work on, the attribute name to define, and the value to give that attribute. Now, no matter what attribute values I give to my object (assuming they're valid attribute names), my class will happily apply them.
So what's the sneakier way than using setattr()? Every object has an attribute named __dict__ that is a dictionary representation of the writable attributes of an object. You can update dictionaries so you could do:
class Thief:
def __init__(self, name, **kwargs):
self.name = name
self.__dict__.update(kwargs)
Usually, though, you don't want to update .__dict__ directly as it's mostly meant to be a read-only resource. Just because you can write to it doesn't mean you should!
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up