2010-03-22 10 views
68

Ich habe eine Klasse mit einer __init__ Funktion.Wie gibt man in Python einen Wert von __init__ zurück?

Wie kann ich einen Integer-Wert von dieser Funktion zurückgeben, wenn ein Objekt erstellt wird?

Ich schrieb ein Programm, wo __init__ Kommandozeile Parsing und ich muss ein Wert gesetzt haben. Ist es OK, setze es in globale Variable und verwende es in anderen Member-Funktionen? Wenn ja, wie? Bisher habe ich eine Variable außerhalb der Klasse deklariert. und setzen Sie es eine Funktion spiegelt sich nicht in anderer Funktion?

+6

Wenn Sie erwogen, einen Fehlercode zurückzugeben, heben Sie stattdessen eine Ausnahme auf. –

+0

Bitte entfernen Sie Ihren Kommentar und aktualisieren Sie Ihre Frage. Du besitzt die Frage. Es ist deine Frage. Bitte korrigieren Sie die Frage, um korrekt zu zeigen, was Ihr eigentliches Problem ist. Du missbrauchst '__init__'; Wir können Ihnen helfen, wenn Sie beschreiben, was Sie wirklich erreichen wollen. –

Antwort

67

__init__ wird benötigt, um keine zurückzugeben. Sie können (oder sollten Sie nicht) etwas anderes zurückgeben.

Versuchen Sie, eine beliebige Instanzvariable (oder Funktion) zurückzugeben.

>>> class Foo: 
...  def __init__(self): 
...   return 42 
... 
>>> foo = Foo() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: __init__() should return None 
+15

+1: Sie können ** nicht ** etwas anderes zurückgeben. Es macht keinen Sinn. –

+63

__init__ gibt das neu erstellte Objekt nicht zurück - wie im TypeError zu sehen ist, muss None zurückgegeben werden, oder? Das neu erstellte Objekt wird von __new__ zurückgegeben, __init__ setzt nur einige seiner Attribute. Aber ja, wie du gesagt hast, macht es keinen Sinn, __init__ oder __new__ zu ändern, um etwas anderes zurückzugeben. – weronika

+0

Wo ist "neu" hier? Ist 'new' in Python implizit? Ich nahm an, dass die Semantik von Python sich von Java und den anderen Sprachen unterscheidet, die dieses Wort verwenden. –

8

__init__ gibt nichts zurück und immer None zurückkehren.

37

Vom documentation of __init__:

As a special constraint on constructors, no value may be returned; doing so will cause a TypeError to be raised at runtime.

Als Beweis dieser Code:

class Foo(object): 
    def __init__(self): 
     return 2 

f = Foo() 

gibt diesen Fehler:

Traceback (most recent call last): 
    File "test_init.py", line 5, in <module> 
    f = Foo() 
TypeError: __init__() should return None, not 'int' 
85

Warum wollen Sie das tun?

Wenn Sie ein anderes Objekt zurückkehren wollen, wenn eine Klasse aufgerufen wird, dann verwenden Sie die __new__() Methode:

class MyClass(object): 
    def __init__(self): 
     print "never called in this case" 
    def __new__(cls): 
     return 42 

obj = MyClass() 
print obj 
+8

Ja, __new__ ist der richtige Weg, etwas anderes als eine Klasseninstanz zurückzugeben, wenn man eine Klasse benutzt ... Ich frage mich nur - gibt es irgendeinen Grund, warum du das wirklich tun willst? – weronika

+22

@weronika Eine Idee: In jeder Situation, in der Sie normalerweise eine Fabrik verwenden würden, aber Sie haben einen Grund, ein Interface zu präsentieren, das wie eine normale Klasseninstanziierung aussieht. Beispiel: Wenn Sie einige neue optionale Parameter in die Klasse "__init__" Ihrer Klasse einfügen, stellen Sie fest, dass Sie eine Klassenfactory benötigen, die Instanzen von spezialisierten Unterklassen zurückgibt, um die gewünschte Flexibilität zu bieten. Die Benutzer Ihrer Bibliothek verwenden jedoch bereits Ihre vorhandene API. Um es zu erhalten, überschreiben Sie '__new__', um Instanzen Ihrer spezialisierten Unterklassen zurückzugeben. –

+6

Wenn Sie ein Beispiel sehen möchten, was Mark Amery gesagt hat, sehen Sie sich den Quellcode des 'datetime' Moduls aus der Standard Library an. Es verwendet '__new__' in genau dieser Weise. – Zearin

12

Die __init__ Methode, wie auch andere Methoden und Funktionen gibt keine standardmäßig in Abwesenheit einer Rückkehr Anweisung, so dass Sie schreiben kann er entweder von diesen mag:

class Foo: 
    def __init__(self): 
     self.value=42 

class Bar: 
    def __init__(self): 
     self.value=42 
     return None 

Aber natürlich ist das return None Hinzufügen Sie nichts kaufen.

Ich bin nicht sicher, was Sie nach, aber Sie könnten in einem von diesen interessieren:

class Foo: 
    def __init__(self): 
     self.value=42 
    def __str__(self): 
     return str(self.value) 

f=Foo() 
print f.value 
print f 

druckt:

42 
42 
+0

ohh..Kann ich Mitglied Mitglied die Klasse? Dann sollte das mein Problem lösen .... danke –

+0

@lakshmipathi, Ja, Instanzvariablen wie diese sind öffentlich. – quamrana

+0

Als ein oneliner, um etwas Wertvolles zu erhalten, das nach der Einleitung einer Klasse zurückgegeben wird: 'f = Foo(). Wert' – JLT

13

Verwendungsbeispiel für die betreffende Angelegenheit kann wie sein :

class SampleObject(object) 

    def __new__(cls,Item) 
     if self.IsValid(Item): 
      return super(SampleObject, cls).__new__(cls) 
     else: 
      return None 

    def __init__(self,Item) 
     self.InitData(Item) #large amount of data and very complex calculations 

... 

ValidObjects=[] 
for i in data: 
    Item=SampleObject(i) 
    if Item:    # in case the i data is valid for the sample object 
     ValidObjects.Append(Item) 

ich habe nicht genug Ruf, so kann ich keinen Kommentar schreiben, es i s verrückt!Ich wünschte, ich es als Kommentar zu weronika posten könnte

+1

Dadurch wird ein NameError ausgelöst: 'self' ist nicht definiert in' __new __ (cls, Item) ' –

2

einfach hinzufügen möchten, können Sie Klassen zurückkehren in __init__

@property 
def failureException(self): 
    class MyCustomException(AssertionError): 
     def __init__(self_, *args, **kwargs): 
      *** Your code here *** 
      return super().__init__(*args, **kwargs) 

    MyCustomException.__name__ = AssertionError.__name__ 
    return MyCustomException 

Das obige Verfahren Sie eine bestimmte Aktion auf eine Ausnahme in Ihrem Test implementieren hilft

+0

Bitte erläutern Sie diesen Code. – nish

Verwandte Themen