How can I make a recursive Python type defined over several aliases?

ぐ巨炮叔叔 提交于 2021-01-22 19:13:55

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!