2012-06-02 7 views
5

Ich habe versucht, dies in den letzten paar Stunden herauszufinden, und ich bin dabei aufzugeben.Python überprüft __init__ Parameter

Wie stellen Sie sicher, dass in Python nur ein passendes spezifisches Kriterium das Objekt erzeugt?

Zum Beispiel möchte ich eine Objekthand erstellen und eine Hand nur initialisieren, wenn ich genug Finger im Initialisierer habe? (Bitte nehmen Sie nur diese als Analogie)

Sprich

class Hand: 
    def __init__(self, fingers): 
    # make sure len(fingers)==5, and 
    #only thumb, index, middle, ring, pinky are allowed in fingers 
    pass 

Dank.

Das sind die nächsten Fragen, die ich gefunden habe, aber einer ist in C++, der andere beantwortet meine Frage nicht.

checking of constructor parameter

How to overload __init__ method based on argument type?

+1

Was möchten Sie passieren, wenn dies nicht der Fall ist? Möchtest du, dass es eine Art von Ausnahme auslöst? – BrenBarn

+0

Ich denke, das wäre ein guter Weg. Nur um sicherzustellen, dass ich kein falsches Objekt erstelle. – chemelnucfin

Antwort

5

Sie haben das definieren __new__ für:

class Foo(object): 
    def __new__(cls, arg): 
     if arg > 10: #error! 
      return None 
     return super(Foo, cls).__new__(cls) 

print Foo(1) # <__main__.Foo object at 0x10c903410> 
print Foo(100) # None 

Das heißt, unter Verwendung von __init__ und eine Ausnahme auf inva Anhebung Lid Args ist in der Regel viel besser:

class Foo(object): 
    def __init__(self, arg): 
     if arg > 10: #error! 
      raise ValueError("invalid argument!") 
     # do stuff 
+5

Das Definieren von '__new__' wird nur selten benötigt, und die Rückgabe von' None' ist schrecklich. Wirf einfach eine Ausnahme, anstatt ein paar Zeilen zu schreiben (oder ein Dutzend Funktionsaufrufe, wenn du Pech hast), bevor du mit einem unerklärlichen Fehler kollidierst. – delnan

+0

@delnan - technisch, wenn das OP ernst meint "nur ein passendes spezifisches Kriterium wird das Objekt erzeugen," würde es notwendig sein, "__new__" zu definieren, denn zu dem Zeitpunkt, an dem '__init__' aufgerufen wird, wurde bereits ein Objekt erstellt Sie haben Recht, dass das Auslösen einer Ausnahme in "__new__" besser wäre als die Rückgabe von None). Aber ich denke das OP bedeutet das nicht wirklich, in diesem Fall ist die '__init__' Version definitiv besser. – weronika

+0

@weronika Wenn es nicht um tiefe Magie und schreckliche Hackereien geht, verhindert das Auslösen einer Ausnahme in '__init__', dass jeder einen Verweis auf das nicht wirklich konstruierte Objekt erhält. Aus dem Blickwinkel eines Beobachters ergibt sich also kein Unterschied, abgesehen davon, dass es sich um eine schreckliche API handelt. – delnan

0

Versuchen Sie behaupten:

class Hand(object): 
    def __init__(self,fingers): 
     assert len(fingers) == 5 
     for fing in ("thumb","index","middle","ring","pinky"): 
      assert fingers.has_key(fing) 
+4

Nein, 'assert' dient zum Verifizieren * interner * Invarianten: Überprüfen Sie, dass * Ihr * Code nicht schrecklich kaputt ist. 'AssertionError' vermittelt dem Anrufer keine nützlichen Informationen und kann sie glauben lassen, dass Ihr Code kaputt ist. Außerdem werden Behauptungen durch "-O" entfernt. Wirf einen 'ValueError' oder' RuntimeError' oder was auch immer für den spezifischen Anwendungsfall geeignet ist. – delnan