简体   繁体   中英

1 as parameter type in function declaration

If you need to specify parameter type in Python, array in my example, you need to write something like this:

def my_function(param: list):
    pass

In Swift you specify parameter type like this:

func myFunction(param: [Any]) {
//
}

One day I made Swift-style mistake and wrote:

def my_function_2(param: []):
    pass

Now I noticed it and try something more strange:

def my_function_3(param: 1):
    pass

All this functions are valid and can be called in Python 3.6. Function with expected parameter type one ... Why it happens, why I don't see any warnings and what kind of variable I would have to pass to functions 2 and 3 to satisfy parameter type I erroneously requested?

Annotations have no meaning to Python's compiler and interpreter. 1 As long as what you type is a syntactically valid expression, Python will evaluate it, store its value as part of the function's annotations, and leave it there for you to do whatever you want with (which is usually nothing).

In fact, you can see this being stored without a problem:

>>> print(my_function_3.__annotations__)
{'param': 1}

The main point of annotations is for using a static type checker, as explained in PEP 484 (and the accompanying PEP 483 and PEP 482 for background).

Static type checking is optional in Python, and generally done with a dedicated tool like mypy , or with tools integrated into IDEs like PyCharm .

If you run such a checker against your code, it will complain. For example:

$ mypy testscript.py
testscript.py:1: error: invalid type comment or annotation

This error means that it can't figure out what type 1 is supposed to be. 2


One last thing:

what kind of variable I would have to pass to functions 2 and 3 to satisfy parameter type I erroneously requested

There's no type that would satisfy that. Python's runtime type rules are more flexible than its (optional) static type rules, but they're not that flexible. 3


1. However, they do have a meaning to at least one thing in the stdlib, the dataclass decorator .

2. Mypy continues on from here, but with no more errors, even if you abuse the parameter in the body or call the function improperly. As far as I can tell, it skips checking the body, and treats the function as if it took any parameters and returned an Any . Which is pretty reasonable—that way you just get this one error instead of hundreds of useless ones that probably wouldn't mean anything.

3. You can't even test for it— isinstance(obj, 1) will raise an exception because 1 is not an instance of type . But if you could, it could only return true if obj was created by calling 1 (or a subclass of 1 , of which there are none) as a metaclass, which is impossible, or if obj.__class__ were set to 1 (or a subclass), which is impossible, or if int had an instance or subclass hook which accepted obj , which it doesn't. But—at least in CPython and PyPy—it won't even get that far. Of course you could always go below Python, below the C API, and directly modify the ob_type field of the struct underneath obj to point at the 1 object, but if you do that, anything you try to do with obj will just segfault.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM