Wie kann man in Python einen Wert von __init__ zurückgeben?

101

Ich habe eine Klasse mit einer __init__Funktion.

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

Ich habe ein Programm geschrieben, in dem __init__Befehlszeilen analysiert werden, und ich muss einen Wert festlegen. Ist es in Ordnung, es in eine globale Variable zu setzen und es in anderen Mitgliedsfunktionen zu verwenden? Wenn ja, wie geht das? Bisher habe ich eine Variable außerhalb der Klasse deklariert. und das Einstellen einer Funktion spiegelt sich nicht in einer anderen Funktion wider?

webminal.org
quelle
8
Wenn Sie einen Fehlercode zurückgeben möchten, lösen Sie stattdessen eine Ausnahme aus.
JoeG
1
Bitte entfernen Sie Ihren Kommentar und aktualisieren Sie Ihre Frage. Ihnen gehört die Frage. Das ist deine Frage. Bitte korrigieren Sie die Frage, um richtig zu zeigen, was Ihr eigentliches Problem ist. Du missbrauchst __init__; Wir können Ihnen helfen, wenn Sie beschreiben, was Sie wirklich erreichen möchten.
S.Lott

Antworten:

116

__init__ist erforderlich, um None zurückzugeben. Sie können (oder sollten zumindest nicht) etwas anderes zurückgeben.

Versuchen Sie, eine 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
Kann Berk Güder
quelle
24
+1: Sie können nichts anderes zurückgeben. Es macht keinen Sinn.
S.Lott
72
init gibt das neu erstellte Objekt nicht zurück - wie im TypeError zu sehen, muss None zurückgegeben werden, oder? Das neu erstellte Objekt wird von new zurückgegeben . Init legt nur einige seiner Attribute fest. Aber ja, wie Sie sagten, macht es keinen Sinn , init oder new zu ändern , um etwas anderes zurückzugeben.
Weronika
Wo ist newhier Ist newin Python impliziert? Ich nahm an, dass Pythons Semantik sich von Java und den anderen Sprachen unterscheidet, die dieses Wort verwenden.
CS95
1
@ Shiva AFAIK, mit new weronika meinte __new __ (self) nicht die allgemeine Java-Semantik.
Harsh Daftary
2
Nur weil es nicht geht, heißt das nicht, dass es keinen Sinn ergibt. Es wäre zum Beispiel schön, Daten von super().__init__der abgeleiteten Klasse zu übergeben, ohne sie über eine Instanzvariable weiterleiten zu müssen.
cz
123

Warum willst du das tun?

Wenn Sie beim Aufrufen einer Klasse ein anderes Objekt zurückgeben möchten, verwenden Sie die folgende __new__()Methode:

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

obj = MyClass()
print obj
Jacek Konieczny
quelle
9
Ja, neu ist der richtige Weg, um etwas anderes als eine Klasseninstanz zurückzugeben, wenn Sie eine Klasse verwenden ... Ich frage mich nur - gibt es einen Grund, warum Sie das tatsächlich tun möchten?
Weronika
33
@weronika Eine Idee: In jeder Situation, in der Sie normalerweise eine Factory verwenden, aber einen Grund haben, eine Schnittstelle zu präsentieren, die wie eine normale Klasseninstanziierung aussieht. Beispiel: Wenn __init__Sie Ihrer Klasse einige neue optionale Parameter hinzufügen , stellen Sie fest, dass Sie eine Klassenfactory benötigen, die Instanzen spezialisierter Unterklassen zurückgibt, um die gewünschte Flexibilität zu gewährleisten. Die Benutzer Ihrer Bibliothek verwenden jedoch bereits Ihre vorhandene API. Um dies beizubehalten, überschreiben Sie die __new__Rückgabe von Instanzen Ihrer speziellen Unterklassen.
Mark Amery
10
Wenn Sie ein Beispiel für das sehen möchten, was Mark Amery gesagt hat, lesen Sie den Quellcode des datetimeModuls aus der Standardbibliothek. Es verwendet __new__genau auf diese Weise.
Zearin
Auch wenn jemand dies tun möchte, stellen Sie sicher, dass Sie von einem Objekt erben, da es sonst nicht funktioniert.
Mino_e
Ich denke, bei diesem Punkt ist es sinnvoller, nur eine reguläre Funktion zu verwenden. Könnte Leuten aus der Java-Dimension etwas fremd sein (funktioniert nicht in Klassen? Häresie!), Aber es ist pythonisch. (Sie können auch Funktionen wie in funtionName.val = .. Eigenschaften zuweisen, was etwas wild ist, aber funktioniert)
Shayne
37

Aus der Dokumentation von__init__ :

Als besondere Einschränkung für Konstruktoren darf kein Wert zurückgegeben werden. Dadurch wird zur Laufzeit ein TypeError ausgelöst.

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'
nosklo
quelle
17

Beispiel Die Verwendung der betreffenden Angelegenheit kann wie folgt sein:

class SampleObject(object):

    def __new__(cls, item):
        if cls.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, also kann ich keinen Kommentar schreiben, es ist verrückt! Ich wünschte, ich könnte es als Kommentar an weronika posten

PMN
quelle
3
Dies wird einen NameError auslösen: selfist nicht definiert in__new__(cls, Item)
Hart Simha
15

Die __init__Methode gibt wie andere Methoden und Funktionen standardmäßig None zurück, wenn keine return-Anweisung vorhanden ist. Sie können sie also wie folgt schreiben:

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

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

Aber natürlich return Nonebringt Ihnen das Hinzufügen von nichts.

Ich bin mir nicht sicher, wonach Sie suchen, aber Sie könnten an einem dieser Punkte interessiert sein:

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

f=Foo()
print f.value
print f

Drucke:

42
42
Quamrana
quelle
Kann ich auf eine Mitgliedsvariable aus der Klasse zugreifen? Dann sollte das mein Problem lösen ... danke
webminal.org
@lakshmipathi, Ja, solche Instanzvariablen sind öffentlich.
Quamrana
Als Oneliner, um nach Beginn einer Klasse etwas Wertvolles zurückzugeben:f = Foo().value
JLT
@JLT Ja, das machst du immer, aber es bedeutet immer noch nicht, dass irgendetwas zurückgegeben wird __init__.
Quamrana
7

__init__gibt nichts zurück und sollte immer zurückkehren None.

gruszczy
quelle
4

Sie können es einfach auf eine Klassenvariable setzen und aus dem Hauptprogramm lesen:

class Foo:
    def __init__(self):
        #Do your stuff here
        self.returncode = 42
bar = Foo()
baz = bar.returncode
PythonPro
quelle
2

Ich wollte nur hinzufügen, dass Sie Klassen in zurückgeben können __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

Mit der obigen Methode können Sie eine bestimmte Aktion für eine Ausnahme in Ihrem Test implementieren


quelle
2
super().__init__kehrt zurück None, also kehren Sie zurück None, was in Ordnung, aber überflüssig ist.
cz
2

init () gibt keinen perfekt gelösten Wert zurück

class Solve:
def __init__(self,w,d):
    self.value=w
    self.unit=d
def __str__(self):
    return str("my speed is "+str(self.value)+" "+str(self.unit))
ob=Solve(21,'kmh')
print (ob)

Ausgabe: Meine Geschwindigkeit beträgt 21 kmh

Vikram Singh Gurjar
quelle
-2

Wenn Sie sich nicht mehr für die Objektinstanz interessieren, können Sie sie einfach ersetzen!

class MuaHaHa():
def __init__(self, ret):
    self=ret

print MuaHaHa('foo')=='foo'
Cosmo
quelle
2
Das ändert nur, was dem Namen selfin diesem Konstruktor zugewiesen ist .
Ondrej K.