2

Type of [[1, 2, 3], 3, [2, 4], 5] is list[list[int] | int]. But what type nested list would have if it has undefined depth e.g. [[[1, 2]], 2, [1, [3, [3]]]], 3, [2, [2]]]?

9
  • 1
    Does this answer your question? Defining a recursive type hint in Python? Commented Aug 13, 2022 at 18:18
  • @VladimirFokow No. In my opinion that question does not provide minimal and reproducible example. Also those answers confusing. One answer is Union[TypeVar('T'), Iterable[TypeVar('T')]] but in accepted answer another code given Union[_, Iterable['_']]. Additionally accepted answer says that "Some types of forward references are handled by PEP0563" without any examples. One comment provide an example list[Union[str, "NestedList"]] but it makes it even more confusing because NestedList was not defined in answer. And once again the question itself is not clear for me. Commented Aug 13, 2022 at 19:14
  • The answer that uses TypeVar('T') says it is just a workaround for previous versions of MyPy - so I wouldn't use it. Commented Aug 15, 2022 at 15:46
  • The comment that provides: NestedList = list[Union[str, "NestedList"]] wasn't meant to answer the question, but rather to illustrate a point that NestedList = list[str | "NestedList"] was not supported. However, that comment gives an answer to this question exactly. Commented Aug 15, 2022 at 15:51
  • @VladimirFokow So can I define NestedList = list[Union[str, "NestedList"]] and use it in function definition like def f(l: NestedList) -> int: ... or do I need to use something like Recursive: TypeAlias = str | list["Recursive"] with def f(l: Recursive) -> int: ... instead? Commented Aug 16, 2022 at 21:47

2 Answers 2

4

You can define a recursive type alias:

T: TypeAlias = list[Union[int, 'T']]
Sign up to request clarification or add additional context in comments.

4 Comments

giving the error: TypeError: unsupported operand type(s) for |: 'type' and 'str'
@illuminato, sorry, my bad. Corrected now
Could you please explain what 'T' means? What is the difference between your code and list[Union[int, TypeVar("T")]]?
@illuminato, Unfortunately, I don't understand in full detail. I think 'T' is a forward reference. If you print(T), you see list[typing.Union[int, ForwardRef('T')]]. However, currently mypy complains (by default): "Cannot resolve name "T" (possible cyclic definition)mypy(error)". 3 days ago Support recursive types #731 issue was closed, saying that now we can set a flag -enable-recursive-aliases.
2

Now that PEP 695 was accepted, you can do the following in Python 3.12:

type NestedList = list[int | NestedList]

Note that you can even drop the " around NestedList because it is no longer a forward reference.

You can even make it a generic type so that you can easily get a nested list of, for example, strings instead of integers:

type NestedList[T] = list[T | NestedList[T]]
nest_string_list: NestedList[str] = []

mypy accepts this since version 1.11 if you use the option enable_incomplete_feature = ["NewGenericSyntax"]. I presume that it will be fully supported in the next version.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.