Можно ли вложить всю функцию?

У меня есть список объектов с именем items . Каждый объект имеет состояние свойства и дочерние объекты, которые являются еще одним списком объектов. И каждый дочерний объект имеет также свойство с именем state . Я хочу знать, что каждый элемент и их дети находятся в государствах счастливыми или веселыми .

Я сделал это со всеми (анализируя состояния предметов):

if all(item.state in ['happy', 'cheerful'] for item in items): pass 

Я хотел бы знать, какой лучший способ сделать то же самое не только с элементами, но и с детьми.

Вы ищете рекурсию здесь:

 def is_happy(items): return all(item.state in ['happy', 'cheerful'] for item in items) and all(is_happy(item.childs) for item in items) 

Как отметил @tobias_k, это должно быть быстрее, так как он повторяется только один раз на элементах:

 def is_happy(items): return all(item.state in ['happy', 'cheerful'] and is_happy(item.childs) for item in items) 

Это, по крайней мере, более читаемо.

В случае, если у вас есть только два слоя объектов, просто для этого тоже может быть трюк.

 def is_happy(items): happy_children = True for item in items: if any(child.state not in ['happy', 'cheerful'] for child in item): happy_children = False break return all(item.state in ['happy', 'cheerful'] for item in items) and happy_children 

Я думаю, это было бы правильно:

 if all(item.state in ['happy', 'cheerful'] and all(c.state in ['happy', 'cheerful'] for c in item.childs) for item in items): pass 

Первый шаг: сгладить список предметов:

 def flatten(items): for item in items: yield item for child in getattr(item, 'children', ()): yield child 

Или используя Python 3.4+:

 def flatten(items): for item in items: yield item yield from getattr(item, 'children', ()) 

И теперь вы можете выполнять итерацию через сплющенные элементы, используя all(..) или как-то иначе:

 is_happy = lambda item: getattr(item, 'state') in ('happy', 'cheerful') are_happy = lambda items: all(map(is_happy, flatten(items))) 

Рекурсия – ваш друг здесь

 def happy(x): return (x.state in ('happy', 'cheerful') and all(happy(xc) for xc in x.children)) 

Это, вероятно, лучше всего сделать вручную.

 def valid(item): return item.state in ['happy', 'cheerful'] for item in items: if not (valid(item) and all(valid(child) for child in item)): break else: # success 

Изменение выражения генератора для работы с этим возможно, но делает его немного взломанным.

 if all(child.state in ['happy', 'cheerful'] for item in items for child in item+[item]): pass 

Поэтому, чтобы ответить на ваш вопрос, да, возможно, он может вложить all функции, и именно так вы можете это сделать, если хотите.