Type Hinting
In this lesson, you’ll learn about type hinting in Python. Type hinting is a formal solution to statically indicate the type of a value within your Python code. It was specified in PEP 484 and introduced in Python 3.5.
Here’s an example of adding type information to a function. You annotate the arguments and the return value:
def greet(name: str) -> str:
return "Hello, " + name
The name: str
syntax indicates the name
argument should be of type str
. The ->
syntax indicates the greet()
function will return a string.
The following example function turns a text string into a headline by adding proper capitalization and a decorative line:
>>> def headline(text, align=True):
... if align:
... return f"{text.title()}\n{'-' * len(text)}"
... else:
... return f" {text.title()} ".center(50, "o")
...
...
>>> print(headline("python type checking"))
Python Type Checking
--------------------
>>> print(headline("python type checking", align=False))
oooooooooooooo Python Type Checking oooooooooooooo
Now add type hints by annotating the arguments and the return value as follows:
>>> def headline(text: str, align: bool = True) -> str:
... if align:
... return f"{text.title()}\n{'-' * len(text)}"
... else:
... return f" {text.title()} ".center(50, "o")
...
...
>>> headline
<function headline at 0x105b81268>
>>> print(headline("python type checking", align="left"))
Python Type Checking
--------------------
>>> print(headline("python type checking", align="center"))
Python Type Checking
--------------------
In terms of style, PEP 8 recommends the following:
- Use normal rules for colons, that is, no space before and one space after a colon (
text: str
). - Use spaces around the
=
sign when combining an argument annotation with a default value (align: bool = True
). - Use spaces around the
->
arrow (def headline(...) -> str
).
To learn more about f-strings, check out the following resources:
00:00 In this video, I’m going to talk to you about type hinting. So, what is type hinting? It’s a formal solution to statically indicate the type of a value. Type hints will help document your code. And notice the idea of hints—they have no runtime effect, they’re only hints and are not enforced on their own. Type hints were first specified in PEP 484, like I mentioned in the previous video, and they were first introduced into Python in version 3.5.
00:33
So, let me show you what it kind of looks like by showing you an example of adding type information to a function. So, what you want to do is annotate the arguments and the return value for this function. So in this example function named greet()
, in the first line, you can see here that the name
argument should be of a type str
(string), and then you can see the return arrow (->
) indicates that this greet()
function is going to return an object of type str
.
01:01
Let’s see what this looks like with your own example. The following function’s going to turn a text string into a headline by adding proper capitalization and then a decorative line. Let’s define this function named headline()
. It’ll accept text
and an optional alignment argument, which is defaulted to True
.
01:21
Then you’re going to do an if
/else
statement. if align:
return
—and here you’re going to create an f-string.
01:29 If you haven’t worked with f-strings before, there’s a course here on Real Python on it and also articles. I’ll have links in the text below.
01:37
Here you’re taking the text
and applying the .title()
method to it to title case it. Put in a line return. And in the next segment for the headline, you’re going to use a dash ('-'
) and use the multiplication or the replication operand (*
) based on the length of the text
to underline it.
01:57
And this will close that f-string. else:
you’re going to make a different one, where it’s not aligned—it’s going to be centered. And this one you’re going to start with a space, again applying title casing to it, which uppercases the first letter of each word in the text
string.
02:12
And here you’re going to run the method on that string of .center()
with a value of 50
characters using the lowercase "o"
. Great!
02:23
So, there’s headline()
. Try it out. You could print a headline saying "python type checking"
, and even though it’s all in lowercase here, you’ll see it title cases and puts the dashes under it, in this case, because there was nothing in there, the default being True
. Try it again,
02:44
and this time go ahead and set an alignment but set it to False
. And that way you’ll use that else
. And here you can see 50 characters with Python Type Checking
centered in the middle of it. Nice! Okay, it’s time for your first type hints. To add information about types to the function, you’re going to simply annotate its arguments and the return values, like this.
03:07
It starts off with putting the first argument of text
with a colon (:
),
03:12
and then the type that it should expect, which is a str
. For align
put in a colon, and in this case, it’s expecting a bool
. And to set a default, you can put that = True
just after that.
03:26
Then you add the hint for the return, which looks like an arrow with a dash (-
) and the greater than symbol (>
). Here, you’re saying the return is a str
, with a colon, and that ends the basic definition. And the rest will be the same as before.
03:54
To reiterate something I said during the intro, adding type hints like this has no runtime effect. They are only hints and are not enforced on their own. For instance, use a wrong type for the admittedly poorly-named align
argument.
04:10 The code still runs without any warning. Something like this,
04:16
and you were to type in align
is, instead of equal to the type of a bool
, is equal to a string with the word "left"
.
04:24
What you would see is left align, but the only reason that it came through—in this case, the string value "left"
has inherently truthiness to it, so it would go down the if align:
statement and return that style.
04:39
Let’s say a user of your function instead types align="center"
. And one nice thing is that you can see here bpython showing that it’s expecting a Boolean. Because it’s looking for a Boolean, a string with the value "center"
is going to be looked at as truthy, giving you the same results as before. To catch this kind of error, that’s when you use a static type checker, and that’s a tool that we’re going to discuss in much more detail.
05:05 It’s going to check the types inside of your code instead of running the code in the traditional sense.
05:12
You may have also seen this type of checking going on inside of an editor or an integrated development environment, such as the one I’m going to show you next, which is PyCharm. So here inside of PyCharm, I’ve saved the headline()
function with the type hints inside of it.
05:28
You can see here, when attempting to put in the unexpected alignment of "center"
as a string, PyCharm shows that it expects a type of bool
and got that string instead.
05:40 Now, this code will run in the same way as it did in the earlier code that you typed in. But here in PyCharm, you’re getting a heads up as to the hints that were put in, and as you go to use those functions, it will warn you, if you will, visually that this is not the expected type that the second argument was looking for. I want to wrap up this video, discussing the formatting of your type hints.
06:06 There’s a few recommendations that actually come from PEP 8. You should use the normal rules for colons, meaning no space before and only one space after the colon, such as here.
06:18
And then you want to use spaces around the equals sign (=
) when combining an argument annotation with a default value. You might’ve noticed that align:
, there’s that space again, bool
, a space before the =
sign and a space after, and then the default value. And, that you want to use spaces before and after that return arrow (->
).
06:44 In the next video, you’re going to take your type checking to the next level using the package Mypy.
Geir Arne Hjelle RP Team on Nov. 3, 2019
I agree that using docstrings for types is a decent alternative for documentation purposes.
The main downside to only using docstrings is that it’s hard to automatically check types in docstrings, because there is no convention everybody follows. This is turn means that it’s hard for tools like static type checkers and IDEs to make use of those types.
Become a Member to join the conversation.
Pygator on Nov. 3, 2019
I get that this may have it’s use, but i’ve seen other coding styles that imply what the arguments should be based on the docstring. I think that is another good alternative.