Python for the .NET developer Transcripts
Chapter: The Python Language
Lecture: Python type annotations
0:00 If you've been longing for types, somewhere, somehow
0:04 in this code, to show up and say, you know
0:06 this next it's actually an integer
0:08 or the return value of this thing is a list
0:11 of numbers or something like that.
0:14 Well, since Python 3.4, we've had the ability
0:18 to specify types, much like Typescript for Python.
0:22 Typescript lets you optionally add types
0:25 it's a little more constrictive
0:27 than what you'll see in Python but you can either run
0:30 plain Python or you can have Python with types
0:33 these days in Python 3.
0:34 So we're going to explore that, and this Python
0:37 with types, in a limited degree, is actually the kind
0:39 that I like best. You'll see that some parts of your code
0:42 don't need any typing and some parts it actually benefits
0:45 them a lot and lights up the editors
0:47 like Pycharm and VS Code and so on
0:49 and it's totally worth it.
0:51 Now I know we haven't yet gotten to classes
0:53 and we're going to focus more on that in a little bit
0:55 but I'm going to use a class here so we can have a type
0:58 to find here, okay? So, if a little bit of the details
1:01 of the class are vague, don't worry about it
1:02 remember next chapter we're diving into classes deep.
1:06 So what we're going to do here, is we're going to define a class
1:08 which is a wizard. Let's remember what the C# one had.
1:14 We had a class which is a Wizard and they had a string name
1:18 and an integer level.
1:20 So, for Python classes
1:22 we go to the constructor to define the fields
1:25 not necessarily at the top level.
1:27 Can do it at the top level
1:28 but we're going to talk about that later.
1:29 So we have not a constructor method or a wizard or whatever
1:34 we just have a what's called a __init__
1:36 double underscore init and down here we don't have a this
1:40 we have a self, so we say self.name =
1:43 let's put a W for the wizard
1:45 and self.level is going to be equal to 0.
1:51 And then what do we have over in the C# world?
1:54 We had a static wizard method so let's go over here
1:56 and define a train method. And it's going to return a wizard
2:00 and this is going be a staticmethod. Right.
2:04 That's what it was before. In C# it was static
2:06 goes there, in Python it was here.
2:09 We'll talk again about that in the classes
2:11 and what we're going to do is we're going to create a Wizard.
2:16 This is like new, but you don't say the new keyword.
2:20 Then we say let's set the base level here
2:24 which is an integer as we'll see.
2:26 Notice there's a level, right, got dot level
2:29 so it's understood this is this type but it doesn't
2:32 really have the typing yet, it's just the editor's
2:33 being really smart. And, yeah, let's just say, we're just
2:37 going to leave the name alone, some wizard, I don't know.
2:42 We could pass this in but the one we did in C#
2:44 didn't have it so let's just leave it like that.
2:47 Alright, so here is the definition of a class
2:49 that is almost like the one we have in C#
2:52 it has a name and a level, it has a train method
2:53 and it returns a wizard. Did I actually return it? No.
2:57 There. Now we have like what we had in C#
3:01 and we don't want this self method for a primer
3:04 for static methods. Okay super, so this is looking pretty good
3:08 and then we had this main business down here.
3:11 And what we said is that Gandolf is a Wizard.train
3:18 set the base level of 7, over here it's going to be 100
3:20 and then we print it out that something like the wizard
3:24 is some level, I'm going to say gandolf.level, like so.
3:28 PyCharm thinks this is misspelled
3:30 of course it's not, right?
3:31 Alright, so let's run this and see what we get.
3:34 Does it behave? Excellent.
3:35 Oh, it didn't level it up.
3:37 Right, that's the other thing we did. We said
3:39 gandolf.level += 1.
3:43 Now it's 101. Perfect. That's what we expect.
3:46 And you might be wondering, okay, well I guess
3:49 there's a class but where's the types, Michael?
3:51 They're not here. Yet.
3:53 This is the untyped version. But Python, like I said
3:57 since version 3.4, we are on 3.7 you can see
4:01 down here on the right, since 3.4 you can define types.
4:05 Actually it's a rich typing system that describes.
4:08 So I can come over here and say, in C# I would say
4:11 something like string name or in Python's types I'd say
4:15 str name. That's not how it works here.
4:18 It's more Typescript like. You say the variable
4:20 and then the type, so name colon str and name colon int.
4:26 So now when I go over here and I say dot level
4:29 dot, notice it's offering auto complete for integers.
4:33 How cool is that? Okay. So it knows that this is an integer
4:38 and down here I can go to this method and say
4:40 this method takes an integer and then
4:44 it has a return value which is this arrow here like that
4:48 and we're going to return a Wizard is what you want to say.
4:52 There's a small challenge about the way
4:55 that the parsing order happens in Python
4:58 so when you're talking within a class
5:01 that it returns that class, you have to put this in quotes.
5:04 But notice it has it like colored to say
5:06 no, this is a special thing, not just a string. Okay?
5:10 So now if I go over here and I could work with this.
5:13 We could say this is a wizard and then gandolf dot name
5:19 obviously it knows that's a string
5:21 but if I said this is something else
5:23 I'm defining it to be an integer
5:24 it gives you a big warning and says no, no, no
5:27 you can't assign a wizard to an integer and down here
5:30 it says the integer doesn't have a level.
5:32 What, are you crazy?
5:33 Right, so you can either omit this
5:35 and it probably can figure out that that's a wizard
5:38 you can see it's doing this here.
5:40 But if you want to be super explicit or some reason
5:43 it doesn't pick it up, you can say this is a wizard.
5:46 Double e here right or for some reason this method
5:48 didn't say what it is but you know what it is
5:50 go like that.
5:52 So check this out. We have Python with types.
5:56 Try it again. It works fine.
5:57 One thing to notice though, this is like an editor helper
6:01 type thing. If this is an integer in C#
6:03 this would crash.
6:04 Here it just keeps running, right?
6:06 You get this warning in the editor but you don't get
6:10 runtime validation. Rarely, not never, but rarely
6:13 does the typing information actually get taken into
6:16 account. For runtime it's for continuous integration tools
6:20 and linters and definitely for editors
6:22 like Pycharm and VS Code. So that's a real big difference.
6:25 But you can have types.
6:26 Now, one more thing we want to do here.
6:29 Why would I give this name as always some other?
6:30 That's weird. I could just set it to be none
6:32 and then people could specify what the level is, right?
6:36 Now notice there's an error.
6:38 In C#, strings are reference types.
6:42 In Python, everything is a reference type. Everything.
6:46 Even numbers are reference types.
6:48 In C# world they should be able to be set to null
6:50 they're None in Python, right?
6:52 The type system is more specific and it has special
6:56 handling for things that can both have a value and be none.
7:00 You have to explicitly say this is a nullable string
7:03 even though it's a reference type.
7:04 So notice here, does expect the string got None.
7:06 So what we have to put an optional string.
7:10 What is optional? This is defined in a library
7:13 called typing. The top, run typing, import optional.
7:18 Now, our none error went away. Right?
7:21 We could do the same thing if we didn't want to start
7:23 with a zero value, we could have an optional int
7:25 set to None. Let's run it one more time.
7:28 The wizard gandolf is at 101 with all sorts of type
7:32 validation in Python. I think that's pretty cool.