问题
I want this logical type structure:
ObjectType = Dict[str, 'EntryType']
ListType = List['EntryType']
EntryType = Union[str, 'ListType', 'ObjectType']
mypy
reports these errors:
mdl/structure.py:7: error: Cannot resolve name "ObjectType" (possible cyclic definition)
mdl/structure.py:7: error: Cannot resolve name "EntryType" (possible cyclic definition)
mdl/structure.py:8: error: Cannot resolve name "ListType" (possible cyclic definition)
...
Is there some way to encode this recursive data type?
I believe I can inline the individual types, typing out the full definition each time, to allow recursion. I'd prefer to avoid this, as it's bulky, and less clear.
回答1:
Recursive types are not yet supported in mypy. They're definitely on the roadmap though, although I'm not exactly sure when the implementation work will begin. It was slated to begin earlier this year, but the prerequisite refactor of the semantic analysis phase (which made a lot of the internal changes needed to cleanly support recursive types) ended up taking longer than expected, so I'm not sure what the new timeline is. Maybe sometime in the next half-year or so?
A possible alternative approach you could look into is to use TypedDicts, which let you assign specific types to certain keys. This is particularly useful if you already know ahead of time what the structure of your input dicts will be -- if you know exactly what keys your ObjectTypes will have, and precisely what they'll map to. Libraries like pydantic are also helpful here, if you prefer working with objects over dicts and prefer not to have to write a bunch of validation logic.
Pragmatically though, if your dict structure is genuinely free-form, it might be best to just go with ObjectType = Dict[str, object]
. After all, in order to identify exactly which EntryType you're dealing with, you're going to have to add in a few isinstance checks anyways to appropriate narrow the type. So, while starting off with object
instead of Union[str, ListType, ObjectType]
will be mildly annoying, it might not be too huge of an imposition depending on what you're doing.
回答2:
mypy does not support recursive types: https://github.com/python/mypy/issues/731
Your type definition is not possible for mypy, and not with any other type checker I know either. Inlining the individual types will give you infinitely long type definitions, as it's recursive.
来源:https://stackoverflow.com/questions/58377361/how-can-i-make-a-recursive-python-type-defined-over-several-aliases