I have just seen the following example in PEP 484:
def greeting(name: str) -> str:
return 'Hello ' + name
print(greeting('Martin'))
print(greeting(1))
As expected, this does not work in Python 2:
File "test.py", line 1
def greeting(name: str) -> str:
^
SyntaxError: invalid syntax
However, it works for Python 3:
Hello Martin
Traceback (most recent call last):
File "test.py", line 5, in <module>
print(greeting(1))
File "test.py", line 2, in greeting
return 'Hello ' + name
TypeError: Can't convert 'int' object to str implicitly
This was unexpected. It does not really check types yet, as you can see with the following example (it runs, but does not throw an exception):
def greeting(name: str) -> int:
return 'Hello ' + name
print(greeting('Martin'))
It seems as if after the :
has to be the name of a function, but the function seems to be ignored:
def aha(something):
print("aha")
return something+"!"
def greeting(name: aha, foo) -> int:
return 'Hello ' + name + foo
print(greeting('Martin', 'ad'))
The same seems to be true for the name after ->
.
Is this type hinting syntax using something else (like Java Modeling language makes use of comments)? When was this syntax introduced to Python? Is there a way to do static type checking already with this Syntax? Does it always break Python 2 compatibility?
Python will always remain a dynamically typed language. However, PEP 484 introduced type hints, which make it possible to also do static type checking of Python code. Unlike how types work in most other statically typed languages, type hints by themselves don't cause Python to enforce types.
Here's how you can add type hints to our function: Add a colon and a data type after each function parameter. Add an arrow ( -> ) and a data type after the function to specify the return data type.
Python has a lot of built-in functions. The type() function is used to get the type of an object. When a single argument is passed to the type() function, it returns the type of the object. Its value is the same as the object.
With Python 3.5, type hints officially became part of the language (PEP 484).
There is no type hinting going on here. All you did was provide annotations; these were introduced with PEP 3107 (only in Python 3, there is no support for this in Python 2); they let you annotate arguments and return values with arbitrary information for later inspection:
>>> greeting.__annotations__
{'name': <class 'str'>, 'return': <class 'str'>}
They are otherwise not consulted at all here. Instead, the error message you got is from trying to concatenate string and integer values in the body of the function:
>>> 'Hello ' + 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
It is a custom type error aimed at providing additional information as to why the str
+ int
concatenation failed; it is thrown by the str.__add__
method for any type that is not str
:
>>> ''.__add__(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
>>> ''.__add__(True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'bool' object to str implicitly
PEP 484 then proposes to make use of those annotations to do actual static type checking with additional tools, but as the introduction of the PEP states:
While these annotations are available at runtime through the usual
__annotations__
attribute, no type checking happens at runtime. Instead, the proposal assumes the existence of a separate off-line type checker which users can run over their source code voluntarily. Essentially, such a type checker acts as a very powerful linter.
Emphasis in the original.
The PEP was inspired by existing tools that use PEP 3107 annotations; specifically the mypy project (which is looping right back by adopting PEP 484), but also the type hinting support in the PyCharm IDE and the pytypedecl project. See Guido van Rossum's original email kickstarting this effort as well as a follow-up email.
mypy apparently supports Python 2 by preprocessing the annotations, removing them before byte-compiling the source code for you, but you otherwise cannot normally use the syntax Python code meant to work in Python 2.
PEP 484 also describes the use of stub files, which sit next to the regular Python files; these use the .pyi
extension and only contain the signatures (with type hints), leaving the main .py
files annotation free and thus usable on Python 2 (provided you wrote Polyglot Python code otherwise).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With