如何使用尚未声明的类的类型注释函数?

时间:2018-09-19 15:21:38

标签: python python-3.x forward-declaration python-typing

在下面的代码中,我有两个类,这些类包含应该返回另一个实例的方法,并且不带注释即可按预期工作:

class Foo:
    def __init__(self, bar = None):
        self.bar = bar or Bar(self)
    def foo(self):
        return self.bar

class Bar:
    def __init__(self, foo = None):
        self.foo = foo or Foo(self)
    def bar(self):
        return self.foo

f = Foo() # verify everything works as intended
assert f.foo().bar() == f 

但是,在代码中添加类型注释会导致NameError上任何表示Foo为类型的注释都为Bar,因为尚未声明Bar:< / p>

from typing import *
class Foo:
    def __init__(self, bar : Optional[Bar] = None):
        self.bar = bar or Bar(self)
    def foo(self) -> Bar:
        return self.bar

class Bar:
    def __init__(self, foo : Optional[Foo] = None):
        self.foo = foo or Foo(self)
    def bar(self) -> Foo:
        return self.foo

在这种情况下,仅切换顺序也无济于事,因为Bar还需要在其注释中引用Foo

如何用尚未声明的类注释函数?


在其他语言中,这将使用前向声明来处理,但是我不知道python中的这种功能。 我尝试了一种“显而易见”的方式来模拟前向声明(声明一个空类),尽管它似乎可以在表面上正常工作,但实际上检查注解会发现这种方法存在缺陷:

from typing import *
class Bar:
    pass

class Foo:
    def __init__(self, bar : Optional[Bar] = None):
        self.bar = Bar(self) if bar is None else bar
    def foo(self) -> Bar:
        return self.bar

class Bar:
    def __init__(self, foo : Optional[Foo] = None):
        self.foo = Foo(self) if foo is None else foo
    def bar(self) -> Foo:
        return self.foo

assert get_type_hints(Bar.bar)['return'] == Foo #correct

# but the original `Bar` used in the annotation is different
# from the redeclared one so this fails:
assert get_type_hints(Foo.foo)['return'] == Bar 

另一种可能性是用Foo的基类对Bar进行注释,但这开始变得很混乱:

from typing import *
from abc import ABCMeta, abstractmethod
class Bar_Base(object, metaclass=ABCMeta):
    @abstractmethod
    def __init__(self):
        pass

class Foo:
    def __init__(self, bar : Optional[Bar_Base] = None):
        self.bar = Bar(self) if bar is None else bar
    def foo(self) -> Bar_Base:
        return self.bar

class Bar(Bar_Base):
    def __init__(self, foo : Optional[Foo] = None):
        super().__init__()
        self.foo = Foo(self) if foo is None else foo
    def bar(self) -> Foo:
        return self.foo

assert issubclass(Foo, get_type_hints(Bar.bar)['return']) #correct
assert issubclass(Bar, get_type_hints(Foo.foo)['return']) #correct

如何用尚未声明的类注释函数?

0 个答案:

没有答案