没有类型注释但具有初始值的变量和参数的类型是什么(在类型注释的意义上,不是 type()
)?例如,
foo = 2
bar = False
baz = MyClass()
bazz = None
从Mypy来看docs和 example code in the Python docs , foo
, bar
, baz
将当前分配int
, False
和 MyClass
。但是,这在任何地方都已标准化吗? bazz
呢?还有呢
def my_func(param1 = 2, param2 = False):
...
?类型检查器会强制传递给 my_func
的参数分别为 int
和 bool
类型吗?
请注意,我对现状不太感兴趣,例如Mypy 等类型检查器的当前实现。相反,我想知道我的问题的答案是否已在任何地方标准化。不幸的是,PEP-484除了:
Type checkers are expected to attempt to infer as much information as necessary.
……但不清楚在上述情况下这到底意味着什么。 (毕竟,param1 = 2
可能只是默认值,实际类型可能更复杂。)
最佳答案
问题一:有默认值但没有类型注解的函数参数的推断类型是什么?
2017年,Guido van Rossum ,Python语言的创造者,建议改PEP 484指定函数参数将从默认值推断出它们的类型。
但是,截至 2020 年 10 月,PEP 484 在 "The Any
type 节中说明:
A function parameter without an annotation is assumed to be annotated with
Any
.
在以下来自 mypy issue #3090 的讨论要点中(从默认值推断参数类型),Jukka 强化了这样一个事实,即默认值不会改变将未注释参数推断为具有类型 Any
的默认行为。
Mypy follows PEP 484. A function parameter without an annotation is the same as having an
Any
annotation, and there is no exception for default values. Here is some rationale for this:
- Often the default argument is not enough to infer a type. For example,
None
doesn't give enough context. With the current rules this doesn't pose a difficulty.- The default argument may not be enough to infer the correct type. For example, if the default is
''
in Python 2, the correct type could well beUnion[str, unicode]
. If the default is0
, the correct type might well befloat
. If the programmer understands the rules for type inference they could override the default type with an annotation as needed, but this would add some extra complexity.- The default value could be a complex expression such as a function call, and thus the type may not [be] obvious from just the default value. Having an annotation makes code like this easier to read.
- If a function has no annotation at all, then the argument type would have to be
Any
anyway. The current rule makes this consistent across functions with no annotations and functions with partial annotations.It all boils down to the current rule being simple and obvious, and in practice it doesn't feel much of a burden to add a few extra :
int
annotations. There is no deep technical reason for the current rule, though it makes type inference easier for mypy.
然后 Guido回复:
OTOH most of those also apply to regular assignments, and there the rule is that
x = 0
infers type
int
forx
. In practice this is very common and useful and only occasionally needs help. So I think we might use the same rule for default values and the complexity of explaining things wouldn't really change. I'm willing to make this a PEP 484 change if enough people care.
问题 2:初始化为 None
的变量的推断类型是什么?
当一个变量被初始化为None
时,直接推断该变量允许显式赋值给None
。如果该变量随后被赋值,例如:
bazz = None
bazz = 42 # type: Optional[int]
然后类型被推断为Optional[int]
。由于 bazz
的推断类型是 Optional[int]
,因此稍后可以将其重新分配为 None
而不会出错。
bazz = None
bazz = 42
bazz = None # Okay
但是,如果 bazz
没有被初始化为 None
,那么下面将是一个错误:
bazz = 42
bazz = None # Error: expression has type "None", variable has type "int"
在没有类型注释的情况下初始化变量的推断类型
PEP 484没有明确讨论根据赋值类型推断未注释变量的类型。但是,从 PEP 484 示例中的注释可以推断,未注释变量的类型确实是根据赋值推断的。
来自 PEP 484 部分的示例 "Scoping rules for type variables"
T = TypeVar('T')
S = TypeVar('S')
class Foo(Generic[T]):
def method(self, x: T, y: S) -> S:
...
x = Foo() # type: Foo[int]
y = x.method(0, "abc") # inferred type of y is str
来自 PEP 484 部分的示例 "Instantiating generic classes and type erasure"
from typing import TypeVar, Generic
T = TypeVar('T')
class Node(Generic[T]):
x = None # type: T # Instance attribute (see below)
def __init__(self, label: T = None) -> None:
...
x = Node('') # Inferred type is Node[str]
y = Node(0) # Inferred type is Node[int]
z = Node() # Inferred type is Node[Any]
关于python - 具有默认值但没有类型注释的函数参数的推断类型是什么?初始化为 'None' 的变量怎么样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64498806/