[Python] Un generatore che non capisco
Pietro Battiston
me a pietrobattiston.it
Ven 8 Nov 2013 12:41:20 CET
Salve a tutti,
ho scritto un generatore con poche righe di codice. Credo che il
contenuto sia inessenziale per la mia domanda, comunque lo trovate in
coda a questa email. Il punto è il seguente:
In [2]: g = enum_balanced(2)
In [3]: list(g)
Out[3]: [{0: [1], 1: []}, {0: [1], 1: []}]
Ora, questo risultato non era quello che mi aspettavo. Armato di
pazienza, mi sono messo a fare un po' di debugging, e...
In [4]: g = enum_balanced(2)
In [5]: list(g.next() for i in range(2))
Out[5]: [{0: [1], 1: [0]}, {0: [1], 1: [0]}]
... mi trovo completamente spiazzato.
C'è ovviamente qualcosa di basilare che mi sfugge riguardi agli
iterables e/o dict, dato che io mi aspetterei che i due comandi sopra
restituissero lo stesso output _qualsiasi cosa_ ci sia scritta nel corpo
g (purché "yieldi" due volte, ovviamente, e non sfrutti variabili
globali...)
Grazie mille di qualsiasi dritta
(N.B: anche eventuali consigli su come migliorare l'algoritmo in sé -
che sostanzialmente genera tutti le sequenze di N numeri
- che finiscono con il numero iniziale
- che non ripetono mai una sottosequenza di lunghezza 2
- e che, possibilmente, non siano isomorfe tra di loro,
... saranno benvenutissimi)
grazie,
Pietro
def enum_balanced(N, prefix=[], links=None):
"""
Restituisci tutti i network balanced di N nodi.
"""
if not links:
links = {i : [] for i in range(N)}
tutti = set(range(N))
# Idea base: c'è un mapping biunivoco tra i balanced strongly
connected e i
# cicli in una cricca che non ripassano mai dallo stesso link.
# Per evitare (parte dei) grafi isomorfi, si può assumere che fino a
che si
# chiude il primo ciclo, i nodi vengono visitati in ordine...
if not prefix:
prefix = [0]
for i in range(1,N):
prefix.append(1)
links[i-1].append(i)
gen = enum_balanced(N, prefix, links)
while True:
try:
n = gen.next()
yield n
except StopIteration:
break
if prefix[-1] == 0 and set(prefix) == tutti:
gr = dict(links)
yield gr
for i in range(N):
# ... ma forse questa altra assunzione non si può fare!
(verificare)
if i != prefix[-1] and (not links[prefix[-1]] or i >
max(links[prefix[-1]])):
links[prefix[-1]].append(i)
gen = enum_balanced(N, prefix+[i], links)
while True:
try:
n = gen.next()
yield n
except StopIteration:
break
links[prefix[-1]].remove(i)
Maggiori informazioni sulla lista
Python