问题
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