Python'da bir değişkenin Yok, Doğru veya Yanlış olup olmadığını nasıl test etmeliyim


147

Üç şeyden birini döndürebilir bir işlevi var:

  • başarı ( True)
  • başarısızlık ( False)
  • akış okuma / ayrıştırma hatası ( None)

Sorum şu: Eğer test etmem gerekirse Trueya Falseda sonucun ne olduğunu nasıl görmeliyim. Aşağıda şu anda bunu yapıyorum:

result = simulate(open("myfile"))
if result == None:
    print "error parsing stream"
elif result == True: # shouldn't do this
    print "result pass"
else:
    print "result fail"

== Trueparçayı kaldırmak kadar basit mi yoksa üç boollu bir veri tipi mi eklemeliyim. İstemediğim simulateben bir hata ile yapmak dış programı o log ve devamı olduğunu istediğiniz tüm olarak işlev bir özel durum.


Yanlış soruyu soruyorsunuz; sonucunuzu tanımlamak için yardım istemelisiniz ... "başarısızlık" ve "hata ayrıştırma akışı" arasında algıladığınız fark nedir, ne anlama gelir, sonuçları nelerdir, arayan kişinin hangi eylemi gerçekleştirmesi muhtemeldir her durumda (geçiş, başarısız, ayrıştırma hatası)?
John Machin

Bir elektrik güç sistemini simüle ediyorum, insanlar evlerine güç kaybederse bu bir başarısızlıktır. Simülasyon dosyasını okuyamıyorsam, bu tamamen farklı bir hatadır.
James Brooks

2
simulateİşlev içinde tüm istisnaları yakalarım; Simülatörün içinde olan hiçbir şeyin programın geri kalanını durdurmasını (ve sonraki öğeyi işlemesini) istemiyorum. Ama cevaplar fikrimi değiştirmemi sağlıyor.
James Brooks

1
@James Brooks: Doğru. Bu, denemenin / işlemenin dışındadır. Eğer simulateyakalayabileceği ve tekrar deneyebileceği şeyler varsa, bu iyi. Ama eğer "başarısız olursa", geri dönmemelidir None. Sadece komut dosyası olarak adlandırılan komut dosyasına bir istisna getirmelidir. Her iki durumda simulateda yapılır. Geri dönmek None, uygun bir istisnayı yükseltmek veya bir istisnanın simulateişleme için çağrı komut dosyasına yayılmasına izin vermek kadar yararlı değildir .
S.Lott

1
@James, except Exception:bunun yerine kullanın. Bu, Warningve ile birlikte tüm "gerçek" hataları yakalar StopIteration. Bu izin verir KeyboardInterruptve SystemExitolsa yoluyla. Bunları gerçekten yakalamak istiyorsanız, muhtemelen "hata" olmadığı için niyetinizi açıkça belgeleyen başka bir dış deney / dış veya başka bir yapı kullanmak en iyisidir. (Ama "neredeyse hiç" demedim ... belki senin durumunda, gerçekten her şeyi kapmak istiyorsun ve hatta Ctrl-C'yi veya sys.exit()çıkmayı, vb. Önlemek istiyorsun )
Peter Hansen

Yanıtlar:


119

İstisnadan korkma! Programınızın sadece oturum açmasını ve devam etmesini sağlamak şu kadar kolaydır:

try:
    result = simulate(open("myfile"))
except SimulationException as sim_exc:
    print "error parsing stream", sim_exc
else:
    if result:
        print "result pass"
    else:
        print "result fail"

# execution continues from here, regardless of exception or not

Ve şimdi, simüle yönteminden tam olarak neyin yanlış gittiğine dair çok daha zengin bir bildirim türüne sahip olabilirsiniz, hata / hata olmadan yeterince bilgilendirici olmamanız durumunda.


Kabul. Yukarıda açıkça görülen daha popüler çözümden çok daha pythonic (C kodu gibi çok fazla kokuyor).
Brandon

7
@Brandon Kabul edilmedi. Bu kod, daha uzun ve daha kötü, yukarıdaki çözümden (veya aşağıdaki geliştirilmiş sürümden) daha az okunabilir: daha fazla girinti, daha farklı ifadeler - ikincisinin neden daha popüler olduğunu tahmin edin ... ;-) Neden olmaya çalışıyorsunuz? Eğer daha garip bir koda yol açarsa 'Pythonic' ...?
Rolf Bartstra

Şimdi "akış ayrıştırma hatası" yerine geri izleme yazdırın ve oyumu aldınız.
CivFan

Tamam, yine de oyumu aldın, ama böyle bir şey yazdırmak istedim traceback.format_exc() . Bu SO cevabına bakın.
CivFan

12
Başlık sorusunun cevabını arayan birçok kişi bu sayfaya gelecek. Çoğumuz için "İstisnadan korkma!" bizim durumumuzla hiçbir ilgisi yok. Sadece Doğru, Yanlış ve Yok'u test etmemiz gerekiyor. Önerilen alternatifiniz bazı durumlar için geçerli olsa da, soruya sorulduğu gibi bir cevap da eklemenin en iyisi olduğunu düşünüyorum.
vastlysuperiorman

163
if result is None:
    print "error parsing stream"
elif result:
    print "result pass"
else:
    print "result fail"

basit ve açık tutun. Elbette bir sözlüğü önceden tanımlayabilirsiniz.

messages = {None: 'error', True: 'pass', False: 'fail'}
print messages[result]

simulateİşlevinizi daha fazla dönüş kodu içerecek şekilde değiştirmeyi planlıyorsanız, bu kodu korumak sorun olabilir.

simulateAyrıca, ayrıştırma hatası üzerinde bir istisna doğurabilir bu durumda ya buradan yakalamak ya da bir düzey yukarı yayılmasını sağlayın ve baskı bit tek hat if-else deyimi düşürülecek olurdu olurdu.


1
İkincisi Doğru veya Yanlış'a karşı açık bir test, değil mi?
Peter Eisentraut

1
Tabii ki, ancak bunların sadece olası dönüş değerleri olduğunu bilerek, bunun bir sorun olduğunu düşünmüyorum.
SilentGhost

ve biraz daha hızlı görünüyor
SilentGhost

a = 'foo' eğer:: 'true' değerini yazdır a aslında DOĞRU değilse, hiçbiri değildir
wesm

17

Asla, asla, asla deme

if something == True:

Asla. Bu bir if-ifadesi için gereksiz koşul kuralı olarak gereksiz olarak belirtilen şeyi gereksiz olarak tekrarladığınız için çılgınca.

Daha da kötüsü, yine, asla, asla, asla deme

if something == False:

Var not . Kullanmaktan çekinmeyin.

Son olarak, yapmak a == Noneverimsizdir. Yapmaka is None . Noneözel bir singleton nesnesidir, sadece bir tane olabilir. Bu nesneye sahip olup olmadığınızı kontrol edin.


3
Eşitliği test Trueetmek gereksiz değildir (mantıklı olmadığını kabul etsem de). __eq__Pratik olarak her şeyi yapabilen bir veya başka bir özel yöntem çağırıyor olabilir.
Scott Griffiths

5
@Scott Griffiths: İyi nokta. Bu gerçekten ve derinden dehşet verici bir senaryo. Aslında durum buysa, program temel beklentilerimizi, bu kara büyü olmadan sıfırdan silinmesi ve yeniden yazılması gereken bir şey yapacak şekilde ihlal eder.
S.Lott

78
'Asla asla asla' ...? Bununla birlikte , örneğin boolean olmayanlardan if something == Truefarklı bir sonuç veren durumlar vardır . yanlış verirken doğru olarak değerlendirir; yanlış ama gerçek! if somethingsomething2==True2None==Falsenot None
Rolf Bartstra

9
-1 Bu cevap yanıltıcı ve tamamen yanlış, çünkü @Rolf Bartstra'nın söylediği doğru. Bu durumda olsa da, ne söylemeye olabilir uygulanacak.
HelloGoodbye

3
-1. Herhangi bir sıfır olmayan ya da boş olmayan veya sıfır-uzunluk değeri yana somethinggetiriTrue ile bool(something). Bu durumda, YALNIZCA yani somethingbir değere sahip olup olmadığını kontrol etmek istiyorsanız . Sonra IMO yapmak zorunda . Trueboolif something == True
Samarth Shah

2

Ben durumlar vardır bile vurgulamak istiyoruz if expr :biri emin olmak istediği için yeterli değildir exprolduğunu Truesadece farklı değil 0/ Nonene olursa olsun, / isden tercih edilmelidir == S.Lott kaçınmak için mentionned aynı nedenle== None .

Gerçekten biraz daha verimli ve kek üzerine kiraz, daha insan tarafından okunabilir.

In [1]: %timeit (1 == 1) == True
38.1 ns ± 0.116 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [2]: %timeit (1 == 1) is True
33.7 ns ± 0.141 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

1
Bir ölçütü bir kez çalıştıramaz ve birinin diğerinden daha verimli olduğunu söyleyebilirsiniz (olsa da). Ortalama olarak nasıl davrandığını görmek için birçok kez (10.000) çalıştırın. \
user1767754

1

İstisna atmanın durumunuz için daha iyi bir fikir olduğuna inanıyorum. Bir alternatif, bir tuple döndürmek için simülasyon yöntemi olacaktır. İlk öğe durum, ikincisi sonuç olacaktır:

result = simulate(open("myfile"))
if not result[0]:
  print "error parsing stream"
else:
  ret= result[1]

1
dönen tuple genellikle bir tuple açma ile iyi gider;)
SilentGhost

2
Ancak kodunuz çok mantıklı değil False, iade edilirse yazdırılır 'error parsing stream'.
SilentGhost

Benzetme yöntemi, ret (False, "hiç bir şey") veya ret (False) ya da True olduğunda (True, ret) döndürmelidir.
kgiannakakis

2
çıkış değerlerini mantığınıza uyacak şekilde yeniden tanımlıyorsunuz, açıklama
olmadan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.