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?


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

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

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'

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


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

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.


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

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


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


-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'

2
Das ändert nur, was dem Namen selfin diesem Konstruktor zugewiesen ist .
Ondrej K.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.