Вы можете создать цепочку логов c самостоятельно. Допустим, у вас есть два итератора разных классов, Foo
и Bar
:
class Foo:
def __init__(self, n):
self._iter = ((i * i for i in range(n)))
def __next__(self):
return next(self._iter)
def foo_method(self):
print("Yay, method in Foo was called")
class Bar:
def __init__(self, n):
self._iter = ((i / 2 for i in range(n)))
def __next__(self):
return next(self._iter)
def bar_method(self):
print("Yay, method in Bar was called")
Итераторы Foo имеют .foo_method()
, а итераторы Bar имеют .bar_method()
.
Теперь давайте объединим их вместе:
class Chain:
def __init__(self, *iters):
self._cursor = 0
self._iters = iters
def __next__(self):
"""
Chain iterators together.
"""
if self._cursor == len(self._iters):
raise StopIteration
try:
return next(self._iters[self._cursor])
except StopIteration:
self._cursor += 1
return next(self)
def __getattr__(self, name):
"""
Pass everything unknown to the current iterator in chain.
"""
if self._cursor == len(self._iters):
raise ValueError("No current iterator")
return getattr(self._iters[self._cursor], name)
Теперь, если вы сделаете что-то вроде
foo = Foo(3)
bar = Bar(3)
chain = Chain(foo, bar)
print(next(chain))
chain.foo_method()
print(next(chain))
print(next(chain))
print(next(chain))
print(next(chain))
chain.bar_method()
, на выходе будет
0
Yay, method in Foo was called
1
4
0.0
0.5
Yay, method in Bar was called
Это не сохраняет класс итераторов, но он позволяет вам получить доступ ко всем методам «текущего» итератора в цепочке.