【发布时间】:2019-05-16 01:13:54
【问题描述】:
前言
我有一个测试,我正在使用嵌套的可迭代对象(嵌套的可迭代对象我的意思是只有可迭代对象作为元素的可迭代对象)。
作为测试级联考虑
from itertools import tee
from typing import (Any,
Iterable)
def foo(nested_iterable: Iterable[Iterable[Any]]) -> Any:
...
def test_foo(nested_iterable: Iterable[Iterable[Any]]) -> None:
original, target = tee(nested_iterable) # this doesn't copy iterators elements
result = foo(target)
assert is_contract_satisfied(result, original)
def is_contract_satisfied(result: Any,
original: Iterable[Iterable[Any]]) -> bool:
...
例如foo 可能是简单的身份函数
def foo(nested_iterable: Iterable[Iterable[Any]]) -> Iterable[Iterable[Any]]:
return nested_iterable
合同只是检查扁平化的可迭代对象是否具有相同的元素
from itertools import (chain,
starmap,
zip_longest)
from operator import eq
...
flatten = chain.from_iterable
def is_contract_satisfied(result: Iterable[Iterable[Any]],
original: Iterable[Iterable[Any]]) -> bool:
return all(starmap(eq,
zip_longest(flatten(result), flatten(original),
# we're assuming that ``object()``
# will create some unique object
# not presented in any of arguments
fillvalue=object())))
但如果nested_iterable 的某些元素是一个迭代器,它可能会耗尽,因为tee 正在制作浅拷贝,而不是深拷贝,即对于给定的foo 和is_contract_satisfied 下一条语句
>>> test_foo([iter(range(10))])
导致可预测的
Traceback (most recent call last):
...
test_foo([iter(range(10))])
File "...", line 19, in test_foo
assert is_contract_satisfied(result, original)
AssertionError
问题
如何深度复制任意嵌套的可迭代对象?
注意
我知道copy.deepcopy function,但它不适用于文件对象。
【问题讨论】:
-
您是否有任何理由反对简单地将嵌套迭代器具体化为嵌套列表?
-
@juanpa.arrivillaga: 是的,我正在编写一个可与任意迭代(有限和无限、用户定义或来自标准库)一起使用的库,并编写基于属性的测试