2012-01-03 4 views
3

Это код, который я нашел в Интернете, и у него нет большого объяснения. Мне просто интересно, как это работает. Я не совсем понимаю yield и часть [s for s in subsets(S)]. Любое понимание было бы высоко оценено!Python 3 - [s для s в подмножествах (S)] и значение

def subsets(aList): 

     if aList ==[]: # base case 
      yield [] 
     else: 
      first = aList[0] 
      rest = aList[1:] 
      for ss in subsets(rest): # include first or don't in each 
       yield ss     # subset of rest 
       yield [first]+ss 

print ("\n testing subsets") 
S = ['A','B','C','D','E'] 

ss = [s for s in subsets(S)] 

print ("The subsets of",S,"are:") 

print (ss) 

ответ

4

subsets является генератором: когда вы называете это, вы создаете объект, который вы можете перебор. Каждый раз, когда итерация запрашивает у него другое значение, он переходит к следующему оператору yield и производит это значение. Это также рекурсивно, поэтому, когда вы запускаете его с пятью элементами, он называет себя последними четырьмя и так далее.

Итак, если он прошел ['A'], он создает второй генератор, который передает пустой список []. Это даст только пустой список, а затем закончить. Главный генератор получит это, даст его (yield ss), затем yield [first]+ss, который будет ['A']. Итоговый результат: [[], ['A']]

[s for s in subsets(S)] - это список. Это эквивалентно:

ss = [] 
for s in subsets(S) 
    ss.append(s) 

В этом случае, это своего рода излишним - вы можете просто сделать list(subsets(S)), чтобы достичь того же. Перечисления списков используются, когда вы хотите что-то сделать для каждой коллекции объектов или если вы хотите их отфильтровать.

2

Способ понимания yield состоит в том, чтобы представить, что это просто оператор возврата, с добавленным завихрением, что при следующем вызове функции выполнение продолжается из инструкции yield. Когда больше нет урожаев, возникает исключение StopIteration.

Более простой пример должен убрать вещи:

>>> def foo(): 
...  for i in range(3): 
...   yield i 
... 
>>> x = foo() 
>>> x 
<generator object foo at 0x7f0cd5c30780> 
>>> x.next() 
0 
>>> x.next() 
1 
>>> x.next() 
2 
>>> x.next() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 
>>> 

Вы можете использовать генератор как итератор, потому for петли просто перехватывать и обрабатывать, что StopIteration исключение внутренне:

>>> x = foo() 
>>> for i in x: 
...  print i 
... 
0 
1 
2 
>>> 

Что касается получения подмножеств, есть более простой способ!
Выйти из рецепта ниже:

>>> from itertools import chain, combinations 
>>> 
>>> def powerset(iterable): 
...  s = list(iterable) 
...  return chain.from_iterable(combinations(s, r) for r in range(len(s)+1)) 
>>> 
>>> S = ['A','B','C'] 
>>> list(powerset(S)) 
[(), 
('A',), 
('B',), 
('C',), 
('A', 'B'), 
('A', 'C'), 
('B', 'C'), 
('A', 'B', 'C')] 

 Смежные вопросы

  • Нет связанных вопросов^_^