3 ms·
That seems to work too.. a = Foo(Foo(Foo(None))) b = Bar(Bar(Bar(None))) c = Hep(Hep(Hep(None))) a.child.junk = 1 # error: Item "Foo" of "
by rcfox 7y ago
That seems to work too..
a = Foo(Foo(Foo(None)))
b = Bar(Bar(Bar(None)))
c = Hep(Hep(Hep(None)))
a.child.junk = 1
# error: Item "Foo" of "Optional[Foo]" has no attribute "junk"
# error: Item "None" of "Optional[Foo]" has no attribute "junk"
b.child.junk = 'a'
# error: Item "Bar" of "Optional[Bar]" has no attribute "junk"
# error: Item "None" of "Optional[Bar]" has no attribute "junk"
c.child.junk = 1.1
# error: Item "Hep" of "Optional[Hep]" has no attribute "junk"
# error: Item "None" of "Optional[Hep]" has no attribute "junk"
a.child = 1
# error: Incompatible types in assignment (expression has type "int", variable has type "Optional[Foo]")
b.child = 1
# error: Incompatible types in assignment (expression has type "int", variable has type "Optional[Bar]")
c.child = 1
# error: Property "child" defined in "Hep" is read-only
# error: Incompatible types in assignment (expression has type "int", variable has type "Optional[Hep]")
I'm using mypy 0.701 with Python 3.7.3.
- neuland 7y agoHey, thanks a lot for pointing this out! Yet another reason to use data classes vs. named tuples. Looks like just plain class level attribute declaration also works: class Node: child: 'Node' I wonder why `typing.NamedTuple` is unique as far as it not working. I know they don't use `eval` and templating to create it anymore. From looking at the code [0], they're using metaclass / __new__. But other than the fact that it uses metaclasses, I'm not sure why it'd have an error. Obviously there's cycle handling in mypy, otherwise none of the examples would work. If I use an example with a metaclass, that also typechecks. So, it's not metaclasses that trigger the error. class NodeBase(type): def __new__(cls, name, bases, attrs): return super().__new__(cls, name, bases, attrs) class Node(metaclass=NodeBase): child: 'Node' # works Edit: it looks like there is now work going into this and other cases where recursive types don't work [1][2]. For example: `Callback = typing.Callable[[str], Callback]` and `Foo = Union[str, List['Foo']]`. [0] https://github.com/python/cpython/blob/3.8/Lib/typing.py#L1593 https://github.com/python/cpython/blob/3.8/Lib/typing.py#L15... [1] https://github.com/python/mypy/issues/731 https://github.com/python/mypy/issues/731 [2] https://github.com/python/mypy/issues/6204 https://github.com/python/mypy/issues/6204