我使用 neovim 并通过 mason-lspconfig 使用 pyright linter 来静态类型检查我的代码。我写了很多类型提示;这是一个例子:
def example(user_input: str) -> None:
tokens: List[Token] = []
position = 0
length_of_input: int = len(user_input)
while position < length_of_input:
match: Union[re.Match[str], None] = None
sliced_input = user_input[position:]
# There's more code but you probably get the point
我有一系列关于类型提示最佳实践的问题:
这就是我要讲的关于满足 linter 的部分。这是我的代码最初的样子:
# There's a lot of context that goes with this but just assume factor_node_result.tokens is a List
tokens = factor_node_result.tokens.copy()
linter 告诉我
None has no method copy()
我把它改成了这样,这样它就不再抱怨了;但是,我的代码的两个版本都可以工作。当我使用这个版本时,linter 就不再抱怨了:
if factor_node_result.tokens is not None:
tokens = factor_node_result.tokens.copy()
事实是,如果你有一个好的 linter 并且编写了不错的代码,那么 linter 抱怨的任何问题都是你的代码的潜在问题。
“但它可以在没有类型的情况下工作”并不能改变这一点。其一,Python 总是在没有类型提示的情况下工作,这不是它存在的原因。其次,除非您绝对确定它可以实现任何可能的值,否则您不能真正说它有效。即便如此,它现在有效的事实并不意味着它将来仍然有效,当您从其他地方调用函数时,或者可能在新版本的 Python 上运行脚本时,具有不同的依赖项等。
至于检查
None
,是的,在某些情况下,如果函数可以合理地返回None
(或者退出而不显式返回任何内容,这是相同的)。例如:
from typing import Optional
def question(answer: bool) -> Optional[int]:
if answer:
return 42
wisdom = question(False)
if wisdom is None:
print("You're not worthy!")
else:
print(f"Your answer is {wisdom}")
但是,始终返回
None
的函数(即仅依赖于副作用,或者只是对对象进行操作的方法)不应需要提示。毕竟,您不会在 None
上调用方法。
所以,对你的问题#1 说“不,除非”,对问题#2 说“不,因为”——这不仅仅是为了满足 linter,而是因为 linter 可能有一个观点。