Nếu sử dụng Python 2.7 bạn cần để giữ chồng của riêng bạn iterables và thực hiện vòng lặp:
from operator import methodcaller
def recursive(obj, iterater, yielder, depth):
iterate = methodcaller(iterater)
xs = [iterate(obj)]
while xs:
try:
x = xs[-1].next()
if len(xs) != depth:
xs.append(iterate(x))
else:
yield getattr(x, yielder)
except StopIteration:
xs.pop()
Đây là một trường hợp đặc biệt của một ichain đệ quy tổng quát hơn từ chức năng iterable:
def recursive_ichain(iterable_tree):
xs = [iter(iterable_tree)]
while [xs]:
try:
x = xs[-1].next()
if isinstance(x, collections.Iterable):
xs.append(iter(x))
else:
yield x
except StopIteration:
xs.pop()
Và một số đối tượng kiểm tra:
class Thing(object):
def __init__(self, thing):
self.thing = thing
class Parent(object):
def __init__(self, *kids):
self.kids = kids
def children(self):
return iter(self.kids)
test_obj = Parent(
Parent(
Parent(Thing('one'), Thing('two'), Thing('three')),
Parent(Thing('four')),
Parent(Thing('five'), Thing('six')),
),
Parent(
Parent(Thing('seven'), Thing('eight')),
Parent(),
Parent(Thing('nine'), Thing('ten')),
)
)
Và thử nghiệm nó:
>>>for t in recursive(test_obj, 'children', 'thing', 3):
>>> print t
one
two
three
four
five
six
seven
eight
nine
ten
Cá nhân tôi muốn có khuynh hướng thay đổi số yield getattr(x, yielder)
thành yield x
để tự truy cập vào các đối tượng lá và truy cập một cách rõ ràng. tức là
for leaf in recursive(test_obj, 'children', 3):
print leaf.thing
Tuy nhiên, giải pháp chung có thể hoạt động trong trường hợp này nhưng chưa có cách nào để thực hiện việc này? – Paradoxis
Tôi có ý nghĩa nhiều hơn khi gọi 'trẻ em' và' x.thing' động – Paradoxis
@Paradoxis Bạn chắc chắn có thể. Giả sử 'children' trả về một iterable. Hãy để tôi sửa đổi câu trả lời của tôi. –