英文:
mypy: Incompatible types in assignment when overwriting a variable
问题
我在运行版本为0.942的mypy时遇到了“assignment”错误,但我无法理解。
我有一个名为price_point
的变量,它采用字符串的形式,并根据字符串是否包含“-”来确定在传递给另一个函数_other_func()
之前是否将该变量转换为列表。该变量也可以为None
。
尝试 1:
代码如下:
def _other_func(
price_points: Optional[Union[List[str], str]]
) -> float:
return 1.0
def get_rate(price_point: Optional[str]) -> float:
"""
Args:
price_point: 表示单个价格或价格范围的字符串,例如 '100' 或 '100-200'。也可以为None。
"""
if price_point and len(price_point_range := price_point.split("-")) > 1:
print(f"Checking range {price_point_range[0]} to {price_point_range[1]}")
price_point = price_point_range
return _other_func(price_point)
错误信息:
error: Incompatible types in assignment (expression has type "List[str]", variable has type "Optional[str]") [assignment]
price_point = price_point_range
^
有人能解释一下为什么mypy
关心这个变量吗?因为_other_func()
输入类型的联合中包含了List
类型。我愿意听取其他建议。
尝试 2:
我认为问题可能与变量的名称有关,因此我尝试了以下方法来将变量重命名,然后将其传递给_other_func()
:
def get_rate(price_point: Optional[str]) -> float:
"""
Args:
price_point: 表示单个价格或价格范围的字符串,例如 '100' 或 '100-200'。也可以为None。
"""
if price_point and len(price_point_range := price_point.split("-")) > 1:
print(f"Checking range {price_point_range[0]} to {price_point_range[1]}")
price_point_input = price_point_range
else:
price_point_input = price_point
return _other_func(price_point_input)
但是相同的错误仍然存在:
error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "List[str]") [assignment]
price_point_input = price_point
^
我不确定是不是因为盯着屏幕看太久的缘故...
英文:
I'm getting an assignment
error when running mypy version 0.942 on my script that I can't make sense of.
I have a variable price_point
that takes the form of a string, and depending on if the string contains a "-", will determine if the variable is manipulated into a list before being passed to another function _other_func()
. The variable can also be None
.
Attempt 1:
The code:
<!-- language: python -->
def _other_func(
price_points: Optional[Union[List[str], str]]
) -> float:
return 1.0
def get_rate(price_point: Optional[str])->float:
"""
Args:
price_point: String representing single price or range of prices
e.g. '100' or '100-200'. Can also be None.
"""
if price_point and len(price_point_range := price_point.split("-")) > 1:
print(f"Checking range {price_point_range[0]} to {price_point_range[1]}")
price_point = price_point_range
return _other_func(price_point)
<!-- end snippet -->
Error returned:
error: Incompatible types in assignment (expression has type "List[str]", variable has type "Optional[str]") [assignment]
price_point = price_point_range
^
Can someone please explain why mypy
is concerned about this variable, since the List
type is accounted for in the Union of types in the _other_func() input? I'd be open to hearing alternate suggetions.
Attempt 2:
I thought the issue might be to do with the name of the variable, so I tried this alternative to rename the variable before passing it to _other_func()
:
<!-- language: python -->
def get_rate(price_point: Optional[str])->float:
"""
Args:
price_point: String representing single price or range of prices
e.g. '100' or '100-200'. Can also be None.
"""
if price_point and len(price_point_range := price_point.split("-")) > 1:
print(f"Checking range {price_point_range[0]} to {price_point_range[1]}")
price_point_input = price_point_range
else:
price_point_input = price_point
return _other_func(price_point_input)
<!-- end snippet -->
But the same error persists:
error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "List[str]") [assignment]
price_point_input = price_point
^
I'm not sure if I'm just having one of those days of staring at the screen for too long...
答案1
得分: 2
静态类型在运行时不能改变。price_point
是一个 Optional[str]
类型,必须在调用 get_rate
函数的整个过程中保持不变。如果你想向 other_func
传递不同类型的值,你需要使用一个不同的变量,可以容纳字符串或列表(或 None
):
def get_rate(price_point: Optional[str]) -> float:
"""
Args:
price_point: 表示单个价格或价格范围的字符串,例如 '100' 或 '100-200',也可以是 None。
"""
arg: Optional[Union[list[str], str]] = price_point
if price_point and len(price_point_range := price_point.split("-")) > 1:
print(f"Checking range {price_point_range[0]} to {price_point_range[1]}")
arg = price_point_range
return _other_func(arg)
然而,我可能会跳过新变量,只是调用 _other_func
两次,每次传递适当的参数:
def get_rate(price_point: Optional[str]) -> float:
"""
Args:
price_point: 表示单个价格或价格范围的字符串,例如 '100' 或 '100-200',也可以是 None。
"""
if price_point and len(price_point_range := price_point.split("-")) > 1:
print(f"Checking range {price_point_range[0]} to {price_point_range[1]}")
return _other_func(price_point_range)
return _other_func(price_point)
更好的做法是考虑将这三种可能性统一到单一类型 list[str]
下,该类型应该包含 0、1 或 2 个字符串:
def _other_func(
price_points: list[str]
) -> float:
match len(price_points):
case 0:
... # 旧的 None 情况
case 1:
... # 旧的字符串情况
case 2:
... # 旧的 list[str] 情况
case _:
raise ValueError("列表中的项目太多")
def get_rate(price_point: Optional[str]) -> float:
arg: list[str]
if not price_point:
arg = []
elif len(price_point_range := price_point.split("-")) > 1:
print(f"Checking range {price_point_range[0]} to {price_point_range[1]}")
arg = price_point_range
else:
arg = [price_point]
return _other_func(arg)
英文:
Static types cannot be changed at runtime. price_point
is a Optional[str]
, and it must stay that way for the duration of the call to get_rate
. If you want to pass a value of a different type to other_func
, you need to use a different variable that can hold either a string or a list (or None
):
def get_rate(price_point: Optional[str])->float:
"""
Args:
price_point: String representing single price or range of prices
e.g. '100' or '100-200'. Can also be None.
"""
arg: Optional[Union[list[str], str]] = price_point
if price_point and len(price_point_range := price_point.split("-")) > 1:
print(f"Checking range {price_point_range[0]} to {price_point_range[1]}")
arg = price_point_range
return _other_func(arg)
However, I would probably skip the new variable, and just make two calls to _other_func
, each with the appropriate argument.
def get_rate(price_point: Optional[str])->float:
"""
Args:
price_point: String representing single price or range of prices
e.g. '100' or '100-200'. Can also be None.
"""
if price_point and len(price_point_range := price_point.split("-")) > 1:
print(f"Checking range {price_point_range[0]} to {price_point_range[1]}")
return _other_func(price_point_range)
return _other_func(price_point)
Even better, consider "unifying" the three possibilities under the single type list[str]
, which should hold 0, 1, or 2 strings.
def _other_func(
price_points: list[str]
) -> float:
match len(price_points):
case 0:
... # Old None case
case 1:
... # Old str case
case 2:
... # Old list[str] case
case _:
raise ValueError("Too many items in the list")
def get_rate(price_point: Optional[str])->float:
arg: list[str]
if not price_point:
arg = []
elif len(price_point_range := price_point.split("-")) > 1:
print(f"Checking range {price_point_range[0]} to {price_point_range[1]}")
arg = price_point_range
else:
arg = [price_point]
return _other_func(arg)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论