Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Type Comments

In this lesson, you’ll learn about type comments. As you saw, annotations were introduced in Python 3, and they haven’t been backported to Python 2. This means that, if you’re writing code that needs to support legacy Python, then you can’t use annotations.

Instead, you can use type comments. These are specially formatted comments that can be used to add type hints compatible with older code. Type comments will not be available in the __annotations__ dictionary. To add type comments to a function, you do this:

Python
def func(arg):
    # type:(str) -> str
    ...

For variables, add the type comment on the same line:

Python
my_variable = 42 # type: int

The type comments are just comments, so they can be used in any version of Python. Try adding type comments to the function from the previous lesson:

Python
>>> import math

>>> def circumference(radius):
...     # type: (float) -> float
...     return 2 * math.pi * radius
...
...
>>> circumference(4.5)
28.274333882308138
>>> circumference.__annotations__
{}

A type comment must start with the type: literal and be on the same line as the function definition or the following line. If you want to annotate a function with several arguments, you write each type separated by comma. You can also write each argument on a separate line with its own annotation:

Python
# headlines.py

def headline1(text, width=80, fill_char="-"):
    # type: (str, int, str) -> str
    return f" {text.title()} ".center(width, fill_char)

print(headline1("type comments work", width=40))

def headline2(
    text,           # type: str
    width=80,       # type: int
    fill_char='-',  # type: str
):                  # type: (...) -> str
    return f" {text.title()} ".center(width, fill_char)

print(headline2("these type comments also work", width=70))

pi = 3.142  # type: float

Run the example through Python and Mypy:

Shell
$ mypy headlines.py
$ python3 headlines.py
---------- Type Comments Work ----------
------------------- These Type Comments Also Work -------------------

If you have errors, for instance if you happened to call headline1() with 67 as the first argument on line 7, and headline2() with width="normal" on line 16, then Mypy will tell you the following:

Shell
$ mypy headlines.py
headlines.py:7: error: Argument 1 to "headline1" has incompatible type "int"; expected "str"
headlines.py:16: error: Argument "width" to "headline2" has incompatible type "str"; expected "int"

Should you use annotations or type comments when adding type hints to your own code? Use annotations if you can, use type comments if you must.

Annotations provide a cleaner syntax, keeping type information closer to your code. They are also the officially recommended way of writing type hints, and will be further developed and properly maintained in the future.

Type comments are more verbose and might conflict with other kinds of comments in your code like linter directives. However, they can be used in code bases that don’t support annotation

00:00 In this video, I’ll show you about type comments. Up to this point, we’ve been talking about type hints and annotations, which are all part of modern Python. Well, what do you do for legacy Python? As discussed, annotations were introduced in Python 3 and they’re not backported to Python 2.

00:19 So up to now, we haven’t discussed any way to add type hints that are compatible with older code. And that’s where type comments come in. So, what are they?

00:29 Well, they’re specially formatted comments. They add type hints that a type checker can use. They’re compatible with older code, and they’re just comments and can be used with any version of Python.

00:44 They’re not going to be available in the __annotations__ dictionary, though. So, let me briefly show you what they look like and then I’ll have you go into an example. For a function, you would annotate the arguments and the return value.

00:57 It would look something like this. On the second line, after you defined your function, you would add a hash mark (#), just like starting a normal comment, type:, space, and then the types inside of parentheses for the argument or arguments.

01:13 Following that, you have the return arrow (->) that you’re familiar with, and ending with the type of the return value. You can add type comments for variables, also, and you would add them on the same line, right after you define the variable.

01:28 Let me take you into a few examples with code and have you test them in Mypy.

01:35 To practice a little bit with type comments, import math, repeating the circumference() example from before. On the second line, that’s where you put the type comments with a hashtag (#) to start the comment, and type:, space. In this case, the circumference() function takes a float and returns a float.

02:00 And then following that, complete the function. So again, circumference() is here, it takes a radius. The comments aren’t going to affect the code at all. If you want to call it, give it a radius of 4.5, there’s your return, both floats going in and out.

02:16 Is there anything in the circumference.__annotations__? No. That dictionary would be empty because these aren’t annotations, these are simply comments. Next, I’d like you to try it out, doing type comments using Mypy to check them. So, make a new file. Actually, you could reuse headlines.py if you still have it.

02:36 So I’m going to open that up and I’m going to hide my terminal a little bit here. Okay. So, I’m going to modify this some. I’m going to call this headline1(). And start with text Here, let me erase most of this. Okay. So, headline1(), text, it’s going to also include a width with a value of 80, and then in this case, you can choose the type of fill character, which you’ll set as a dash ("-"). Okay, define that function. Again, second line. To put in your type comments, type:. In this case, you have multiple arguments, so the first one is a type of str (string), the second is a type of an int, and the third is a type of str.

03:15 You just simply put the arguments one after another, with a comma (,) in between them, followed by a space. Then the return will be a str. So, there’s your type comment.

03:25 And have it make an f-string, take that text, title-case it with the method, and then use the .center() method,

03:36 using the parameter of width and the fill character for the arguments for .center(). Next, print out headline1(), using "type comments work" as the text and a narrower width of 40. Great. Resave.

03:54 You can run Mypy against it. I need to exit the REPL.

03:58 mypy headlines.py. And you can see it went through and did the checking and it didn’t find any kind of errors in it. That’s great! Now, there is another way you could have defined headline().

04:12 I’ll call it headline2(). In that case, you would open up the parentheses and you could put each argument on a separate line with the inline # type: comment.

04:23 So, hashtag (#) to start the comment, space, type, colon (:), and that’s a str for the text. Second is the width with a default value of 80, and that’s a type of int. And the fill character

04:41 with its default of a dash, and that’s a type of str. And here, when you close the parentheses, you would add the type for the return. And this looks a little different.

04:56 You use the parentheses, (...), and say that it returns a str. And here to finish the return, you could just copy it here. I’ll have you just copy it here. Oops, I missed the r. Great. Okay, so then here,

05:27 I’m going to put a width=80—or, in this case, put a width=70. All right. Save it again. So, here’s the two styles for type comments. After saving,

05:38 run it through Mypy again, headlines.py.

05:45 And you can see here, it had no issues with that. So then headlines did its type checking correctly. If I do python3 headlines.py, you can see both of the functions are working fine.

05:58 What if we screwed up here and put in something like width="normal" instead of the integer? Or potentially up here, we give it a value of 67 instead of the text string. Hit save.

06:17 We can now test to see if mypy headlines—what happens. Oh, so if you run mypy headlines on that version, it says here at line 7, Argument 1 to "headline1" has incompatible type "int"; expected "str".

06:32 So that’s working fine. And the Argument "width" of "headline2" has incompatible type of "str"; expected "int". Yeah, great! So Mypy is doing its job. Again, that needs to be an int and then here…

06:48 And resave again. Let me run Mypy one more time. Yeah. That time it ran. And again, no errors reported. Great!

07:00 And just one last thing, if you needed to add type comments for variables, it’s done really similarly, like the second example, where you would say, say you’re creating a variable named pi and you want to assign 3.142 as a value to it. Then you would add the comment after it, the type comment after it, # type: float. And again, you can run through mypy headlines. If you did something weird in here again, maybe you said, “Oh, that’s supposed to be an int,”

07:34 you can see here on line 18, Incompatible types in assignment, expression has a float, variable has a type of int. Okay, yeah, that’s supposed to be a float. So, you can see type comments working.

07:48 Now that you’ve seen type comments and you might be thinking about, should you use type annotations or should you use type comments? You really should use annotations if you can, and only use type comments if you must.

08:03 Here’s a few of the reasons. Annotations provide a much cleaner syntax. Annotations are the officially recommended way for type hints. And annotations will be further developed and properly maintained. Type comments can be much more verbose. And then type comments might also conflict with other kinds of comments that you have in your code already, like linter directives. In the next video, I’ll have you dive much deeper into code and play around with Python types and also import the typing module.

Avatar image for francoisg

francoisg on Dec. 12, 2019

small heads up: 04:00 you call mypy on headlines instead of headline1

Avatar image for francoisg

francoisg on Dec. 12, 2019

nevermindm it seems I was not really awake sorry

Become a Member to join the conversation.