Do type annotations in Python enforce static type checking?

杀马特。学长 韩版系。学妹 提交于 2021-01-29 10:33:07

问题


I'm trying to enforce some static type checking in a project written in Python, using typing module.

When I define a function like the one from the doc

def greeting(name: str) -> str:
    return 'Hello ' + name

and try to do something like greeting(3), I indeed got the following error

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in greeting
TypeError: must be str, not int

But when I again define a function called test

def test(a: int) -> None:
    print(a)

and do test("a"), I have a printed without any errors raised. I also tried

def test(a: str) -> None:
    print(a)

and do test(3), but no TypeError is raised.

I defined both functions in exactly the same environment, i.e. an interaction python session using iTerm. Why would this happen?


回答1:


Type annotations in python DO NOT enforce static type checking.

Python's still a dynamic language, where the interpreter checks whether it has a method to do the operation, add a str ("hello") and add an integer (3), when it reaches this line during the execution loop. Pep-484 states the core-developers don't want to change this with annotations.

If you look at the documentation, it is called 'type hints'. Hints are not enforcement.

Type hints are really for developers and their tools (like IDEs) to better document the expected type of a parameter. But adding this form of documentation does not place any restriction the argument. It is merely documentation. In fact, it's best to think of these annotations as documentation.

The error you are seeing happens without those annotations. E.g.

>>> "Hello" + 3
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str

It is possible to develop tools to do this if you want. The annotation on the object's

__annotations__

Why is it like this? In python, we generally don't do explicit type checks. Instead, we just try to call the method, like "add 'hello' and 3" and let there be an error. It's up to the caller of the function to provide the correct types. But this also means it's up to the writer of the function to document the parameter accurately. Type hints help describe the expected type, and make it available on the object, which is useful for other tools to then hook into. Previously, we'd write this stuff as documentation, like:

def greeting(name):
    """Greeting to name
    :param name: str, the name to greet
    Returns string"""
    return "hello" + name

Use duck typing to help you out The type error you've raised would be avoided if you used built-in string formatting or cast the incoming value to a string before calling add. For example, to avoid the error you saw, you could:

 def greeting(name: str) -> str:
    """Greeting to name
    :param name: str, the name to greet
    Returns string"""
    return "hello" + str(name)

def greeting(name: str) -> str:
    """Greeting to name
    :param name: str, the name to greet
    Returns string"""
    return "hello {}".format(name)



回答2:


The clue here is in the line number: the error is occurring inside the function, when you try to add 'Hello' and 3. The type annotations are checked for syntactic correctness by the interpreter, but are not otherwise actioned.

There are projects like mypy that use the annotations for status type checking and various other purposes.




回答3:


Type annotations are comments. They do not affect the Python interpreter's basic functioning in any way. Python does not check whether the arguments you provide match the type specified in the type annotation!



来源:https://stackoverflow.com/questions/54734029/do-type-annotations-in-python-enforce-static-type-checking

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!