2011-08-18 12 views
27
Ben bu basit örnekte olduğu gibi listelerde arama yapmak için jeneratörleri kullanıyorum

:StopIteration yerine None döndürmek için bir Python jeneratörü nasıl alabilirim?

>>> a = [1,2,3,4] 
>>> (i for i, v in enumerate(a) if v == 4).next() 
3 

(Tıpkı yukarıdaki birine göre çok daha uzun listeleri kullanıyorum örneğin biraz çerçeveye ve girişler bir olan için bunun yerine i == 666 bu değişebilir mi diye, bir StopIteration döneceğini biraz daha karmaşık int daha. Öyle tüm listeleri Şimdi her seferinde onları bulun)

geçilen olmayacak bunu bu şekilde çünkü 'can a numaralı telefondan 666 girişini bulun.

Nasıl yerine None döndürmesini sağlayabilirim? Tabii ki try ... except maddesine sardım, ama bunu yapmak için daha pythonic bir yol var mı?

+0

sorabilir miyim? –

+0

Zaten geçtiğiniz bir şey için arama yaparsanız ne bekliyorsunuz? Neden sadece 'pythonic' şeklini kullanarak değil, eğer ben: ... '? –

+0

@Manny D, '' i varsa, bulunan maddenin indeksini almak istiyorsanız yardımcı olmaz. – senderle

cevap

70

Eğer next yerleşik işlevi olmayan (3.x __next__ ile değiştirildi) next yöntem kullanmalıdır 2.6+ Python kullanıyorsanız. next yerleşik yineleyici tükendiği takdirde yerine StopIteration yetiştirme, geri dönmek için isteğe bağlı varsayılan argüman alır: Eğer şeyler aramak için jeneratörleri kullandığınız neden

next((i for i, v in enumerate(a) if i == 666), None) 
+1

+1 yeni şeyler anlamaya, bu bunu yapmanın en iyi yoludur. – senderle

+0

Yerleşik işlev değişmişti bilmiyordum. Bu kesinlikle çok daha kolay hale getirir – c00kiemonster

7

Sen (Hiçbiri) ile jeneratör zincir edebilirsiniz:

from itertools import chain 
a = [1,2,3,4] 
print chain((i for i, v in enumerate(a) if v == 6), (None,)).next() 

ama a.index (2) tam listesini, 2 bulunduğunda, arama tamamlandığında çapraz olmayacağını düşünüyorum. Eğer bu test edebilirsiniz:

>>> timeit.timeit("a.index(0)", "a=range(10)") 
0.19335955439601094 
>>> timeit.timeit("a.index(99)", "a=range(100)") 
2.1938486138533335 
+1

Zincir şey çok zekiydi, bunu düşünmüyordu. Evet 'index()' fena değil, ama benim gerçek durumumda, liste girdileri değişkenlerden ziyade nesneler olduğu için kullanamıyorum. DÜZENLEME: Nesnenin kendisini aramaktan ziyade nesne özelliklerini ve diğer eğlenceli şeyleri karşılaştırıyorum. – c00kiemonster

+1

Bunu söylediğim için üzgünüm, ama bu aşırı karmaşık bir çözümdür. 'Next' yerleşik işlevi zaten bu işlevselliği temiz bir şekilde sunar. @ C00kiemonster, seni kullanmak (ve kabul) gerektiğini düşünüyorum [zeekay cevabı] (http://stackoverflow.com/questions/7102050/how-can-i-get-a-python-generator-to-return-none-rather -than-StopIteration/7102204 # 7102204). – senderle

+0

başka bir şey olmadığını Endişelenmeyin, iyi bir yol ... Python – c00kiemonster

İlgili konular