2010-09-16 20 views
6

Tercih sırasına göre birkaç gruba rastgele üye döndüren bir işlevim vardı."pass" dışında bir neat alternatifi var mı?

def get_random_foo_or_bar(): 
    "I'd rather have a foo than a bar." 

    if there_are_foos(): 
     return get_random_foo() 

    if there_are_bars(): 
     return get_random_bar() 

    raise IndexError, "No foos, no bars" 

Ancak get_random_foo yaptığı ilk şey bu yüzden there_are_foos gereksiz bir IndexError değilse Foo'larınız vardır doğrulayıp yükseltmek şudur: Böyle bir şey çıktı. Ayrıca, bir veritabanı dahil ve ayrı işlevler kullanarak bir eşzamanlılık sorunu oluşturur. Buna göre, bunun üzerine böyle bir şey yazdım:

def get_random_foo_or_bar(): 
    "Still prefer foos." 

    try: 
     return get_random_foo() 
    except IndexError: 
     pass 

    try: 
     return get_random_bar() 
    except IndexError: 
     pass 

    raise IndexError, "No foos, no bars" 

ama bu kadar az okunabilir bulmak ve ben pass kullanmak için bir neden olmadı gibi instictively yanlış geliyor önce.

Neatre verimli bir desen var mı, yoksa pass kabul etmeyi mi öğrenmeliyim?

Not: Diğer türler daha sonra eklenebileceğinden, yuvalamadan kaçınmak istiyorum.


Düzenleme

Teşekkür pass ince olduğunu söyledi herkes - o güven verici!

Ayrıca istisnayı değiştirmeyi None döndürme değeriyle önerenler için teşekkürler. Bunun nasıl yararlı bir kalıp olduğunu görebilirim, ancak bu durumda semantik olarak yanlış olduğunu tartışabilirim: işlevlerin imkansız bir görevi yerine getirmeleri istenerek bir istisna oluşturmaları istenmiştir. random modülünün davranışını izlemeyi tercih ederim (örn. random.choice([])).

+1

except' tablolarda 'kullanım muhtemelen Python pass'' en yaygın kullanımıdır. Bu yüzden alışırdım. –

+0

"Fakat bunu daha az okunabilir buluyorum ... o, nesnel olarak yanlış hissettiriyor" - bunu kültürel bir sorun olarak düşünün. Şimdi garip görünüyor, ama dili kullanmanın en temiz yolu. – detly

cevap

13

Tam olarak nasıl yazacağım. Bu basit ve mantıklı. pass ifadelerinde sorun görmüyorum.

Yinelemeyi azaltmak ve gelecekteki türleri eklemeyi düşünüyorsanız, bunu bir döngü haline getirebilirsiniz. bu senin gözlerine daha hoş olmadığını Sonra, bir işlevsel olarak eşdeğer continue açıklamaya pass değişebilir:

for getter in (get_random_foo, get_random_bar): 
    try: 
     return getter() 
    except IndexError: 
     continue # Ignore the exception and try the next type. 

raise IndexError, "No foos, no bars" 
1

sadece bu iki varsa, olabilir o ikiden fazlası var her zaman sadece ...

try: 
    return get_random_foo() 
except IndexError: 
    try: 
     return get_random_bar() 
    except IndexError: 
     raise IndexError, "No foos, no bars" 

varsa, ne yazdım tamamen kabul edilebilir görünüyor.

2

pass gayet (! orada dildeki bir nedeni var -), ancak bir pasaportlar (etkileşimli yorumlayıcı isteminden import this)

try: return get_random_foo() 
except IndexError: 
    try: return get_random_bar() 
    except IndexError: 
     raise IndexError "no foos, no bars" 

Python'un Zen "düz iç içe daha iyidir" diyor, ama yuvalama inci de geçerli: ücretsiz alternatif biraz daha iç içe alır e dil, (muhtemelen aydınlanmış) karar verdiğinizde kullanmanız için o bilge koandan daha iyisini yapabilirsin! -) ("Yoldaki Budala tanışırsan ..." gibi).

2

get_random_foo(), bir indeks param olarak alınmadığında bir IndexError'ı yükseltmek için bana biraz garip geliyor (ancak bağlamda daha mantıklı olabilir). Neden get_random_foo() veya sarıcıya sahip değilseniz, hatayı yakalayın ve bunun yerine Yok'unu döndürün.

def get_random_foo_wrapper(): 
    try: 
     return get_random_foo() 
    except IndexError: 
     return None 

def get_random_foo_or_bar(): 
    "I'd rather have a foo than a bar." 

    return get_random_foo_wrapper() or get_random_bar_wrapper() or None 

Düzenleme: Sonra or karşılaştırma

+0

İşaretimi rastgele modülden aldım - 'random.choice ([]) 'komutunu çalıştırmayı deneyin. İlginç bir çözüm olsa da, teşekkürler! –

0

üzerine kurulan KÖTÜ olan üzerlerinden atlayacak foo & bar False değerlendirebilir nesnelerdir if (0 veya '' derler) bahsetmeliyiz Peter Gibson'un önerisi, verilen bir istisnayı yutan genel bir sarıcı işlevi oluşturabilir. Ve sonra sağlanan bir istisna için böyle bir genel sarıcı döndüren bir işlev yazabilirsiniz. Ya da, istisnalar için sağlanan listesi için heck. Eğer gerçekten durum mesajı (sadece tip) gerekmiyorsa

def maketrap(*exceptions): 
    def trap(func, *args, **kwargs): 
     try: 
      return func(*args, **kwargs) 
     except exceptions: 
      return None 
    return trap 

def get_random_foo_or_bar(): 
    mytrap = maketrap(IndexError) 
    return mytrap(get_random_foo) or mytrap(get_random_bar) or None 
0

:

def get_random_foo_or_bar(): 
    try: 
     return get_random_foo() 
    except IndexError: 
     return get_random_bar() # if failing at this point, 
            # the whole function will raise IndexError 
+0

Sanırım hataya aynı olmak ve bir yoruma ihtiyaç duymaktan ziyade hatayı “get_random_foo_or_bar” dan açık bir şekilde yükseltmeyi tercih ederim. Ayrıca bu, get_random_foo_or_bar'dan uygun bir istisna mesajı göndermemi sağlıyor. –

0

o âciz ise get_random_foo/bar() Bir IndexError zam yapması gerekli mi?

onlar Hiçbiri iade ederse, bunu yapabilirsiniz:

def get_random_foo_or_bar(): 
    return get_random_foo() or get_random_bar() 
İlgili konular