Python 类型检查工具 beartype
¶
Python 代码中的类型提示并不是需要强制满足的。如果我们希望代码使用者严格遵循类型提示,在类型不符时抛出错误,可以使用 beartype
进行类型检查。
安装¶
使用¶
仅针对自己编写的代码¶
若我们正在开发一个 Python 包,并需要对这个包内的所有代码添加类型检查,可以在包的 __init__.py
文件中添加:
针对依赖的外部代码¶
若我们需要对依赖的外部代码进行类型提示,但不需要抛出错误,而是警告用户,可以用:
Python
# ....................{ BIG BEAR }....................
# Warn about type hint violations in *OTHER* packages outside your control;
# only raise exceptions from violations in your package under your control.
# Again, at the very top of your "{your_package}.__init__" submodule:
from beartype import BeartypeConf # <-- this isn't your fault
from beartype.claw import (
beartype_all,
beartype_this_package,
) # <-- you didn't sign up for this
beartype_this_package() # <-- raise exceptions in your code
beartype_all(
conf=BeartypeConf(violation_type=UserWarning)
) # <-- emit warnings from other code
针对单个函数¶
若我们只需要对某个函数进行类型检查,可以使用装饰器:
Python
from beartype import beartype
# Annotate @beartype-decorated classes and callables with type hints.
@beartype # <-- you too will believe in magic
def quote_wiggum(lines: list[str]) -> None:
print("“{}”\n\t— Police Chief Wiggum".format("\n ".join(lines)))
更多使用方法可以参考官方文档。
不对某些内容进行类型检查¶
参考:How do I NOT type-check something?
方法 1:
Python
# Import the requisite machinery.
from beartype import beartype, BeartypeConf, BeartypeStrategy
# Dynamically create a new @nobeartype decorator disabling type-checking.
nobeartype = beartype(conf=BeartypeConf(strategy=BeartypeStrategy.O0))
# Avoid type-checking *ANY* methods or attributes of this class.
@nobeartype
class UncheckedDangerClassIsDangerous(object):
# This method raises *NO* type-checking violation despite returning a
# non-"None" value.
def unchecked_danger_method_is_dangerous(self) -> None:
return 'This string is not "None". Sadly, nobody cares anymore.'
方法 2:
Python
# Import more requisite machinery. It is requisite.
from beartype import beartype
from typing import no_type_check
# Avoid type-checking *ANY* methods or attributes of this class.
@no_type_check
class UncheckedRiskyClassRisksOurEntireHistoricalTimeline(object):
# This method raises *NO* type-checking violation despite returning a
# non-"None" value.
def unchecked_risky_method_which_i_am_squinting_at(self) -> None:
return 'This string is not "None". Why does nobody care? Why?'