Python for the .NET developer Transcripts
Chapter: The Python Language
Lecture: Concept: Python function overloading
0:00 Let's quickly review functions in Python.
0:03 Here, we have a function called named arguments
0:06 and it has one required positional parameter
0:09 called name, ironically.
0:11 And then, it takes arbitrary positional arguments
0:15 *args, remember that's like params, object array
0:18 but we just say *.
0:19 And then, we can pass arbitrary keyword arguments to it
0:23 and that appears in the dictionary, kwargs.
0:27 I don't really love that style because
0:29 it doesn't tell me what arbitrary keywords I could pass.
0:33 A way to accomplish almost exactly the same thing
0:37 like 90% of the time, if you just have default values
0:40 like this times here.
0:42 If you could've said times=1
0:44 but you don't have to, well, you could also just say
0:47 times=1 as a default argument
0:50 and it turns out the editors give you way more help
0:53 because if ask what is the signature of named args
0:57 in the top one, it tells me I can pass anything.
1:00 I don't know what type those are.
1:01 I don't know the values of them, the names
1:03 of the parameters are, the list of options, nothing.
1:07 And this is prevalent in Python
1:08 and I kind of hate it because usually what you can do
1:11 is just name out the optional
1:14 named arguments as default values
1:16 and folks can decide to pass them by name or not, right?
1:20 So really, really nice to do this second one.
1:24 I feel it's better than the top one.
1:25 There's a few use cases where you really don't know
1:27 what could go in there 'cause your passing it along
1:29 but most of the time, you actually know.
1:31 It's just you don't want to say.
1:32 So anyway, I kind of like the bottom
1:34 say hello version over the named args.
1:37 One thing you do want to be careful about though
1:39 with these default values here, these can be dangerous.
1:43 So see this say no, as in no, no, no, don't do this?
1:47 This one actually is a bit of an anti-pattern
1:50 and let me tell you why.
1:51 If you pass a mutable type or if you set a mutable type
1:55 for the default value, this could go really, really wrong
1:59 and let me tell you how.
2:00 You might think when you call this function
2:03 the default value is created
2:04 and set each time the function is called
2:07 but that's not actually where the default value is set.
2:10 The default value is set when that module, that file
2:13 is loaded, once, ever, so there is a singleton list
2:19 that is the default value for names.
2:21 That singleton is, well, it's a singleton
2:25 and that means it's shared by everyone who calls
2:27 that function every time.
2:29 So imagine something happens inside
2:32 that function where names is altered, right?
2:35 An item is added or removed to names if it's empty.
2:38 Well, guess what.
2:39 Now the default value has that change reflected in it
2:42 or worse, if this function returns names
2:45 makes some changes, adds more names
2:47 and returns that list, then it's open
2:49 to the rest of the program to possibly add
2:52 or remove items from that default value
2:54 so never, never put a mutable value here.
2:57 The way you would accomplish this
2:59 is you would say names=None
3:00 and then, in that function you say
3:02 if names is None, names=, like this.
3:06 And that way, you get a new copy every time you call it
3:09 not the one that got set when you imported the module.
3:12 That's super not obvious, so I wanted to call it out
3:15 and make it really clear. This seems okay
3:17 but it turns out to actually be an anti-pattern.