2012-05-23 22 views
17

Bir Python sınıfında, bu yöntemin çalıştırılmasından önce sınıfın diğer özelliklerinin bazıları değiştiğinde örnek yöntemden ne tür bir hata çıkarmalıyım?Sınıf durumu geçersiz olduğunda ne tür bir hata çıkıyor?

InvalidOperationException, "Nesnenin geçerli durumu için bir yöntem çağrısı geçersiz olduğunda atılan istisna" yı kullanacağım C# arka planından geliyorum, ancak eşdeğeri built-in exception in Python bulamadım.

ValueError'u yükselttim ("işlev, işlev parametreleriyle doğru olduğunda yerleşik bir işlem veya işlev doğru türden ancak uygun olmayan bir değere sahip bir argüman aldığında ortaya çıkar"). Bunun teknik olarak self parametresi için geçersiz bir değer olduğunu varsayalım; tedavi etmek için doğru yol bu mu? Örneğin, bu deyimsel: raise ValueError("self.foo must be set before running self.bar()")?

+1

ValueError bana iyi görünüyor. Bir kullanıcının problemle ilişkisini tanımlaması için yeterince yakın. Ayrıca python gibi yanlış bir istisna kullanmak için bileğinize tokat alamaz. Bu diğer hatalardan ayırmak için yeterince yakın. – jdi

+1

Daha fazla ayrıntı vermeye ihtiyaç duyuyorsanız, neden kendi istismarınızı yapmıyorsunuz? –

+1

@LattyWare: Yeni istisna tiplerinin usulsüz nilüfer alt sınıflarını kakmak için görüşmeler gördüm. Bol miktarda yerleşik yapı olduğunu ve sadece karmaşıklığı arttırdığını ileri sürüyorlar. – jdi

cevap

17

ValueError en iyi şey yükseltmek için bu durumda. Python için, kendi yarattığınız için built-in exception types kullanmayı tercih etmelisiniz. Yalnızca yakalamanız gerekeceğini düşündüğünüzde yeni özel kural türleri oluşturmalı ve yerleşik türleri yakalarken davranışlarından çok farklı davranmalısınız. Bu durumda, durum ortaya çıkmamalı - bunu yakalamayı beklemiyorsunuz çünkü bu, söz konusu sınıfı kullanmada bir hata olduğunu gösteriyor. Bunun için sadece başka bir isme sahip olmak için yeni bir tür oluşturmaya değmez - bu, ValueError()'a ilettiğiniz mesaj dizesinin ne için olduğunu belirtir.

Sınıfınızı yeniden yapılandırabilmek için böyle bir geçersiz durum mümkün olmaz mı?

+2

Teşekkürler - önemli olan, hiç kimsenin istisnayı yakalayamayacağıdır (bu bir "[boneheaded exception"] olurdu) (http://blogs.msdn.com/b/ericlippert/archive/2008/09 /10/vexing-exceptions.aspx) İstemcide – Justin

+1

Hiç kimse onu yakalayamazsa ve sadece bir iç kontrol olarak görev yaparsa, bunun yerine "assert" kullanabilirsiniz. Bir iddiadaki ifade yanlış olduğunda, bir AssertionError istisnası ortaya çıkar. – MarioVilas

+3

Geçersiz durumdaki bir aramada 'ValueError' öğesini yükseltmek için iyi bir örnek Python'un kendisinde bulunabilir: http://hg.python.org/cpython/file/v3.3.1/Lib/subprocess.py#l881 –

1
class InvalidOperationException(Exception): 
    pass 

SYS_STATE = 1 

def something_being_run(): 
    if SYS_STATE < 2: 
     raise InvalidOperationException 

Bunun gibi bir şey mi demek istiyorsunuz? Kendi İstisna türler yapmak için alt sınıf istisnası olmamalıdır neden bir neden göremiyorum, ama bu bana gelmeden önce eski Oracle PL/SQL Dev olabilir ...

+1

Yaptığınız tek şey bir ad ve geçiş için alt sınıfsa, gerekli değil. – jdi

+2

Birisi daha sonra bu istisnayı yakalayacaksa gereklidir. OP'nin yerine yerleşik bir istisna istediğini kabul etsem de bana göre doğru bir çözüm gibi görünüyor. – MarioVilas

3

Pythonic yöntem, hatalı bir durumda olmasına rağmen bir yöntem çağrısının çökmeyeceği bir durumda nesneyi bırakmaz. Bunlar, programın üstesinden geldiği nokta, hatanın oluştuğu yer olmadığı için en zor böcekler. Örn.,

örn.

class PseudoTuple(object): 
    """ 
The sum method of PseudoTuple will raise an AttributeError if either x or y have 
not been set 
""" 
    def setX(self, x): 
     self.x = x 

    def setY(self, y): 
     self.y = y 

    def sum(self): 
     """ 
In the documentation it should be made clear that x and y need to have been set 
for sum to work properly 
""" 
     return self.x + self.y 

class AnotherPseudoTuple(PseudoTuple): 
    """ 
For AnotherPseudoTuple sum will now raise a TypeError if x and y have not been 
properly set 
""" 
    def __init__(self, x=None, y=None): 
     self.x = x 
     self.y = y 

Ne yapılmamalıdır olan

class BadPseudoTuple(PseudoTuple): 
    """ 
In BadPseudoTuple -1 is used to indicate an invalid state 
""" 
    def __init__(self, x=-1, y=-1): 
     self.x = x 
     self.y = y 

    def sum(self): 
     if self.x == -1 or self.y == -1: 
      raise SomeException("BadPseudoTuple in invalid state") 
     else: 
      return self.x + self.y 

gibi bir şey ben bu pythonic sloganı altında gelir düşünüyorum:

O izin almak olandan af dilemesini kolay

Olağan dışı durum Sınıfı yanlış kullanmanın bir kullanıcı hatası olmaktan ziyade normal yürütme sırasında gerçekleşmesi beklenirse, kendi istisnaınızı yaratmanız makul görünmektedir. StopIteration ve yineleyiciler bunun bir örneğidir.

+2

garanti edemezsiniz, "Yok" ifadesinin geçersiz durumdan daha iyi bir -1 değeri gibi özel bir değer. Benim durumumda, kontrol ettiğim koşul dört farklı özelliği içeren oldukça karmaşıktır, bu yüzden, sınıfın kullanıcısına rehberlik etmek için bir hata mesajı eklemek istiyorum. Yöntemin amacı, harici bir sisteme komut göndermektir, bu yüzden geçersiz değerleri göz ardı edemem. – Justin

+1

Belki de 'IOError' kullanmak isteyebilirsiniz. Bütün hatalardan sonra, nesnenin durumu hakkında, iletişimin gerçekleştirilemeyeceği anlamına gelen bir şey vardır. – Dunes

-1

Sorun fonksiyon parametreleri ile eklendiğinde yapıyorsun gibi, bir ValueError yükseltmek gerektiğini düşünüyorum ve bir AttributeError sorun ayarlanmalıdır bir öznitelik ile olduğu zaman.

Ayrıca, daha özel bir Özel Durum yapmak için AttributeError alt sınıfını da kullanabilirsiniz, ancak bunu gerekli görmüyorum. Hata iletinizle AttributeError İstisnası yeterince açık.

+1

AttributeError, bir öznitelik eksik olduğunda, nesnelerinizin iç mantıksal durumu ile ilgisi yoktur. – MarioVilas

0

ValueError bana uygun, ama bence AssertionError daha uygun. Temel olarak, API tasarımcısı tarafından yapılan iddiayı ihlal eder.

+1

Sanırım, "AssertionError" çoğunlukla "assert" ve benzeri yapılara ayrılmıştır, bu yüzden muhtemelen bunu yükseltmek için "assert" ifadesini kullanırsınız. Ancak bu ifade, tercüman konfigürasyonuna bağlı olarak bazen göz ardı edilir, çünkü 'assert' genellikle üretim için değil, test amaçlıdır. Bu yüzden, test istisnalarını etkileyeceğinden, AssertionError'un bu eyalet için en iyi seçenek olmadığını düşünüyorum. – MarSoft

5

Geçersiz durumu bildirmek için tüm yerleşik istisnalardan en uygun olanını RuntimeError buluyorum.

Python 2.7.10 (default, Jul 13 2015, 12:05:58) 
[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from threading import Thread 
>>> Thread().join() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 938, in join 
    raise RuntimeError("cannot join thread before it is started") 
RuntimeError: cannot join thread before it is started 

Hatta CPython uygulaması kendisi kütüphaneleri arasında belirli istisna tiplerinin kullanımı hakkında tutarlı olmadığını fark önemlidir:

o CPython nasıl kullanıldığını bu örneğe bakın. Bunun yerine bazen ValueError kullanılır, ancak bence, Python belgelerinden yapılan açıklama, kullanımının diğer durumlar için ayrıldığını gösterir. RuntimeError, daha genel bir istisnadır ve bir kod parçası, bir nesne geçersiz bir durumda olduğunda duruma benzer bir şekilde uygun bir giriş verildiğinde doğru bir şekilde davranamazsa kullanılmalıdır.

İlgili konular