Например:
>>> f = lambda x: x * 2
>>> input = [([1, 2], [3, 4]), {"foo": 5, "bar": 6}]
>>> nested_map(f, input)
[([2, 4], [6, 8]), {"foo": 10, "bar": 12}]
< /code>
В идеале он будет дружелюбен к типам в том смысле, что он сказал бы статической проверке, что выходной объект имеет точно такую же структуру, что и вход. Хотя это, вероятно, гораздо сложнее достичь. < /P>
У меня есть функционально работающая версия для этого, но: < /p>
Я не смог должным образом типа «гомогенный» natedtuple < /code> s; и < /li>
Это не очень хорошо работает при проверке статического типа. < /li>
< /ul>
import inspect
from collections.abc import Iterable
from typing import Any, Callable, Generator, NamedTuple, cast
type MappableIterable[A] = list[A] | tuple[A] | dict[Any, A] | Generator[A]
type NestedIterable[A] = A | MappableIterable["NestedIterable[A]"]
def nested_map[A, B](
f: Callable[[A], B], nested_structure: NestedIterable[A]
) -> NestedIterable:
"""
Takes a nested iterable structure and applies f to all of its nodes,
returning them in the same structure.
"""
structure = type(nested_structure)
match nested_structure:
case dict():
return {
k: nested_map(f, v)
for k, v in nested_structure.items()
}
# NamedTuple
case _ if hasattr(structure, "_fields") and isinstance(
getattr(structure, "_fields"), tuple
):
d = {
k: nested_map(f, v) for
k, v in cast(NamedTuple, nested_structure)._asdict().items()
}
return cast(NestedIterable, structure(**d))
case _ if inspect.isgenerator(nested_structure):
return ( nested_map(f, s) for s in nested_structure )
# Have to check str first since it is an Iterable
case str():
return f(nested_structure)
case Iterable():
structure = cast(type
- , structure)
return structure(map(lambda s: nested_map(f, s), nested_structure))
case _:
return f(nested_structure)
< /code>
Знаете ли вы, есть ли способ кодировать информацию структуры (или, по крайней мере, тот факт, что она тот же для ввода и вывода) в текущей системе Hint-Hint Python? Я безуспешно пытался «параметризовать одну переменную другой» с чем-то подобным, но, конечно, это не сработало: < /p>
def nested_map[A, B, C: NestedStructure](f: Callable[[A], B], nested_structure: C[A]) -> C:
...
Подробнее здесь: https://stackoverflow.com/questions/796 ... -in-python