我有一个代码,其中 Main 类接收 Child 类的实例作为属性。 这些属性类型为可选,因为它们在应用程序启动时未定义,在这种情况下它们会被初始化。
Main 实例的方法在很多地方都依赖于那些 Child 对象的方法和属性。
这是我的代码的一个简化示例:
import typing
class Child():
def print_foo(self) -> None:
print("foo")
class Main():
def __init__(self) -> None:
self.child: typing.Optional[Child] = None
def initialise(self) -> None:
if not self.child:
self.child = Child()
def foo(self) -> None:
self.child.print_foo()
main = Main()
main.initialise()
main.foo()
我正在尝试使用 mypy 在我的应用程序管道中强制执行正确的类型检查。
我的问题是,由于这些子属性是可选的并且最初未定义,mypy 抱怨说
Item "None" of "Optional[Child]" has no attribute "print_foo" [union-attr]
我可以检查定义相关属性的每个方法,例如
def foo(self) -> None:
if self.child:
self.child.print_foo()
else:
raise Exception("child not defined")
但我不想这样做,因为那意味着为遇到该问题的每个方法重复此代码,而我的应用程序中有很多。
我尝试解决它的一种方法是使用装饰器:
import typing
def check_defined(func):
def wrapper(*args, **kwargs):
_self = args[0]
if not _self.child:
raise Exception("child not defined")
else:
return func(*args, **kwargs)
return wrapper
class Child():
def print_foo(self) -> None:
print("foo")
class Main():
def __init__(self) -> None:
self.child: typing.Optional[Child] = None
def initialise(self) -> None:
if not self.child:
self.child = Child()
@check_defined
def foo(self) -> None:
self.child.print_foo()
main = Main()
main.initialise()
main.foo()
但这不会改变类型检查的结果。
因此我的问题是双重的:
谢谢!