Son zamanlarda, önemsiz kısıtlamalarla belirli dizileri oluşturmak için bir işlev yazdım. Sorun, doğal özyinelemeli bir çözümle geldi. Şimdi, nispeten küçük girdiler için bile dizilerin birkaç bin olduğu, bu nedenle algoritmamı tüm dizilerle bir listeyi doldurmak için kullanmak yerine bir jeneratör olarak kullanmayı tercih ederim.
İşte bir örnek. Bir dizgenin tüm permütasyonlarını özyinelemeli bir fonksiyonla hesaplamak istediğimizi varsayalım. Aşağıdaki saf algoritma fazladan bir 'depolama' argümanı alır ve bir tane bulduğunda buna bir permütasyon ekler:
def getPermutations(string, storage, prefix=""):
if len(string) == 1:
storage.append(prefix + string) # <-----
else:
for i in range(len(string)):
getPermutations(string[:i]+string[i+1:], storage, prefix+string[i])
storage = []
getPermutations("abcd", storage)
for permutation in storage: print permutation
(Lütfen verimsizliği önemsemeyin, bu sadece bir örnektir.)
Şimdi fonksiyonumu bir üreteç haline getirmek, yani onu depolama listesine eklemek yerine bir permütasyon vermek istiyorum:
def getPermutations(string, prefix=""):
if len(string) == 1:
yield prefix + string # <-----
else:
for i in range(len(string)):
getPermutations(string[:i]+string[i+1:], prefix+string[i])
for permutation in getPermutations("abcd"):
print permutation
Bu kod yok değil (boş bir jeneratör gibi işlev davranır) çalışır.
Bir şey mi kaçırıyorum? Yukarıdaki yinelemeli algoritmayı, yinelemeli bir algoritma ile değiştirmeden bir jeneratöre dönüştürmenin bir yolu var mı ?
yield from getPermutations(string[:i] + string[i+1:])
, bu birçok yönden daha etkilidir!