-
Notifications
You must be signed in to change notification settings - Fork 769
Python Typing constructs that are confusing
This is a list of typing contructs that could be confusing for people coming to Python typing from other languages:
This one is always easy to forget. It's rather long so it gets its own page:
https://github.com/microsoft/pylance-release/wiki/Covariance-and-Contravariance
Relevant documentation: https://docs.python.org/3/library/typing.html#typing.Tuple
Tuple types can have a number of forms.
x: Tuple[int] = (1)
x: Tuple[int, float] = (1, 2.0)
x: Tuple[int, ...] = ()
The weird one being the last one. That ...
means zero or more ints in the tuple. However, it's only allowed once. This is illegal:
x: Tuple[int, int, ...] = (1)
If you wanted a tuple with 1 or more ints, you'd do the following instead:
y: Tuple[int, *Tuple[int, ...]] = (1,)
This example:
The intuition for TypeVar('d', bound=int)
is that it's a type that's derived from int. Same with NewType('e', int)
.
But for some reason that's not true even though it behaves that way.
See https://peps.python.org/pep-0695/#upper-bound-specification
TypeVars are like templates being declared outside of their usage. They're not instantiable.
NewTypes are for enforcing an abstraction around another type. To make sure that that item is not just an alias. https://peps.python.org/pep-0484/#newtype-helper-function
For more information, see the advanced type topic for Pyright.
https://peps.python.org/pep-0570/#syntax-and-semantics
def foo(x: int, y: int, /, pos_or_keyword_arg, *, **kwargs):
pass
There are special indicators that separate positional and keyword only arguments. You can't pass anything for these parameters, it's just a way to indicate that in the function definition.
They do have a use though. Here's one such example:
https://github.com/microsoft/pylance-release/issues/2346#issuecomment-1031757771