Method Arguments5:33 with Kenneth Love
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,
**kwargs all you want!
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")
**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:
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
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
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
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 it's
items method and pull out the two values from each iteration into
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!
I'm pretty sure you could guess how this works. 0:00 But let's talk a bit about how to make methods that take parameters 0:02 other than self. 0:05 Python doesn't like to surprise us and definitely doesn't hear. 0:07 Just like with standard functions, 0:10 we can add any number of parameters to our methods. 0:11 We can use args and kwargs too if we want. 0:14 So, let's add a new method down here and let's call this hide. 0:17 And lets take self, of course, an instance, and lets take a new argument 0:22 which is light_level, right, because it's easier to hide in the dark, and 0:26 we're going to return if self.sneak is equal to true, or sneaky rather, 0:29 and that the light_level is less than ten. 0:33 Okay? So, if the light_level's is less than ten, 0:39 you can always hide so long as you're a sneaky thief. 0:41 Sort of the rules of our game. 0:45 All right, so let's go and try this again in our shell. 0:46 And let's make Thief. 0:54 All right, so now let's try kenneth.hide when the white level's (4). 0:56 True. 1:02 Cool, and that's expected because I am sneaky and 1:03 the light level is below ten, okay? 1:07 Let's try kenneth.hide and the light level is 14. 1:10 And that one comes out as false, okay? 1:13 And then, if we do kenneth.sneaky equals false and kenneth.hide and 1:16 it's pitch black at zero, false. 1:21 So, cool. 1:23 That's working just like I expected. 1:24 Let's talk about a special method though and one that you'll likely use a lot. 1:27 When you create a new instance of a class, Python looks for 1:31 a method named double underscore init double underscore. 1:34 The double underscores, or as I call them, dunders, on both sides, 1:38 indicate that the method is the one that Python will run on its own and 1:42 that we don't usually need to worry about. 1:45 At least we don't have to use it explicitly, 1:48 we don't have to call it ourselves. 1:50 Now, this method lets us control how the classes are created or 1:52 initialized, which is why it's called init. 1:55 Let's make our Thief a little smarter in its creation. 1:58 So, let's add def, init, and there's those double underscores. 2:01 And this'll take self, it'll take a name, it'll take a sneaky argument. 2:04 We'll automatically set to True, and 2:09 it'll take any other kwargs that happen to come in, any other keyword arguments. 2:12 So, we'll say self.name = name, and we'll say self.sneaky = sneaky. 2:16 All right? And everything else, 2:22 we're gonna leave alone. 2:23 And we could actually make this a little easier here. 2:24 We could say, instead of checking the self.sneaky, 2:27 we could return self.sneaky and that one. 2:34 So, that way our two methods are pretty similar to each other. 2:38 Okay. 2:43 So, we have a couple of new things in this one. 2:44 Let's try it out. 2:46 Okay, back into Python from characters import Thief, 2:48 kenneth equals Thief, and we forgot to write a name, okay? 2:55 So, let's add a name under this. 3:00 So, I'm gonna add in Kenneth, and I'm gonna go ahead and say false for 3:01 the sneaky part. 3:05 Okay, cool. 3:07 So now, let's do kenneth.name. 3:08 That gives me back Kenneth, nice. 3:11 And if we do kenneth.sneaky, we get back false. 3:13 So, when I created the instance, I passed two arguments, 3:16 which Python plopped into the two arguments in the init method. 3:19 Then we assigned each of those to a different attribute on the instance, 3:22 by using self, right? 3:26 self.name = name, self.sneaky = sneaky, that's awesome, okay. 3:27 So, what about this kwargs thing? 3:32 Well if you remember, **kwargs is the dictionary full of key value pairs. 3:34 Let's loop through that and assign all of those things to the instance. 3:39 So, down here below that, let's do four key value in kwargs.items, 3:46 and then we'll use a new method, or a new function rather called setattr, 3:52 and let's specify the instance to set it on, 3:58 we attribute the set and the value to get to that attribute. 4:01 So, the set out of function is amazingly useful in situations like this because we 4:06 don't know the name of the attributes that we need to create. 4:11 So, said do that with this random values that come in this users supplied values. 4:16 There is a sneakier way of doing this but is less clear. 4:22 So, I tend to avoid it. 4:26 I’ve put it in the teachers notes though if you’re curious. 4:28 But, for now let’s try this out. 4:30 Pull our console back up. 4:35 Python. 4:37 From characters, import thief. 4:39 Kenneth equals thief. 4:43 I keep forgetting to supply that name. 4:44 So, we'll do Kenneth, we'll leave sneaky alone. 4:47 We'll say scars=None, and 4:50 favorite_weapon="Wit", cool. 4:54 So, if I do kenneth.name, we get back Kenneth, If I do kenneth.sneaky, 4:59 I should get True, because that's what we set as the default. 5:03 And if I do kenneth.favorite_weapon, I get Wit, cool. 5:06 So, it looks like that works and that lets us add extra information to our instances. 5:11 You're doing great with building simple custom classes and 5:16 using attributes and methods. 5:19 You'll find yourself using that set outer pattern, so 5:20 make sure you add it to your notes and practice it a few times. 5:22 In fact, let's do a code challenge or two around it. 5:25 Then come right back for a serious talk about one of the hardest parts of object 5:27 oriented programming, design. 5:31
You need to sign up for Treehouse in order to download course files.Sign up