¿Cómo devolver un valor de __init__ en Python?


102

Tengo una clase con una __init__función.

¿Cómo puedo devolver un valor entero de esta función cuando se crea un objeto?

Escribí un programa, donde se __init__analiza la línea de comandos y necesito tener algún valor establecido. ¿Está bien configurarlo en la variable global y usarlo en otras funciones miembro? Si es así, ¿cómo se hace? Hasta ahora, declaré una variable fuera de la clase. ¿Y configurar una función no se refleja en otra función?


8
Si estaba considerando devolver un código de error, genere una excepción en su lugar.
JoeG

1
Elimina tu comentario y actualiza tu pregunta. Eres dueño de la pregunta. Es tu pregunta. Solucione la pregunta para mostrar correctamente cuál es su problema real. Estás haciendo un mal uso __init__; podemos ayudarlo si describe lo que realmente está tratando de lograr.
S.Lott

Respuestas:


117

__init__Se requiere devolver Ninguno. No puede (o al menos no debería) devolver otra cosa.

Intente hacer lo que quiera para devolver una variable de instancia (o función).

>>> 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: No puedes devolver otra cosa. No tiene ningún sentido.
S.Lott

72
init no devuelve el objeto recién creado; como se ve en TypeError, es necesario devolver None, ¿verdad? El objeto recién creado es devuelto por new , init solo establece algunos de sus atributos. Pero sí, como dijiste, cambiar init , o new , para devolver algo más, realmente no tiene sentido.
weronika

Donde esta newaqui ¿Está newimplícito en Python? Asumí que la semántica de Python era diferente de Java y los otros lenguajes que usan esta palabra.
cs95

1
@Shiva AFAIK, new weronika significaba __new __ (self) no la semántica general de Java.
Harsh Daftary

2
El hecho de que no se pueda hacer no significa que no tenga sentido. Por ejemplo, sería bueno pasar datos desde super().__init__la clase derivada sin tener que transmitirlos a través de una variable de instancia.
cz

123

¿Por qué querrías hacer eso?

Si desea devolver algún otro objeto cuando se llama a una clase, utilice el __new__()método:

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

obj = MyClass()
print obj

9
Sí, nuevo es la forma correcta de devolver algo que no sea una instancia de clase cuando se usa una clase ... Me pregunto: ¿hay alguna razón por la que realmente quieras HACER eso?
weronika

33
@weronika Una idea: en cualquier situación en la que normalmente usarías una fábrica, pero tienes alguna razón para querer presentar una interfaz que parezca una instancia de clase normal. Ejemplo: cuando agrega algunos parámetros opcionales nuevos a su clase __init__, se da cuenta de que realmente, para brindar la flexibilidad que desea, necesita una fábrica de clases que devuelva instancias de subclases especializadas. Pero los usuarios de su biblioteca ya están usando su API existente. Para conservarlo, anula __new__para devolver instancias de sus subclases especializadas.
Mark Amery

10
Si desea ver un ejemplo de lo que dijo Mark Amery, consulte el código fuente del datetimemódulo de la Biblioteca estándar. Se usa __new__exactamente de esta manera.
Zearin

Además, si alguien quiere hacer esto, asegúrese de heredar del objeto, de lo contrario, no funcionará.
Mino_e

En cierto modo, creo que, en este punto, solo usar una función regular tiene más sentido. Puede ser un poco ajeno a la gente de la dimensión Java (¿funciones no en clases? ¡Herejía!) Pero es pitónico. (También puede asignar propiedades a funciones como en funtionName.val = .. que es un poco salvaje pero funciona)
Shayne

37

De la documentación de__init__ :

Como restricción especial de los constructores, no se puede devolver ningún valor; al hacerlo, se generará un TypeError en tiempo de ejecución.

Como prueba, este código:

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

f = Foo()

Da este error:

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

17

El uso de muestra del asunto en cuestión puede ser como:

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)

No tengo suficiente reputación por lo que no puedo escribir un comentario, ¡es una locura! Ojalá pudiera publicarlo como comentario para weronika


3
Esto generará un NameError: selfno está definido en__new__(cls, Item)
Hart Simha

15

El __init__método, al igual que otros métodos y funciones, devuelve Ninguno de forma predeterminada en ausencia de una declaración de retorno, por lo que puede escribirlo como cualquiera de estos:

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

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

Pero, por supuesto, agregar el return Noneno te compra nada.

No estoy seguro de lo que buscas, pero es posible que te interese uno de estos:

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

f=Foo()
print f.value
print f

huellas dactilares:

42
42

ohh .. ¿Puedo acceder a la variable miembro fuera de la clase? Entonces eso debería resolver mi problema ... gracias
webminal.org

@lakshmipathi, Sí, las variables de instancia como esta son públicas.
Quamrana

Como un delineador para obtener algo valioso devuelto después del inicio de una clase:f = Foo().value
JLT

@JLT Sí, siempre puedes hacer eso, pero aún así no significa que se devuelva nada __init__.
quamrana


4

Puede simplemente establecerlo en una variable de clase y leerlo desde el programa principal:

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

2

Solo quería agregar, puede devolver clases en __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

El método anterior le ayuda a implementar una acción específica ante una excepción en su prueba


2
super().__init__está regresando None, por lo que está regresando None, lo cual está bien, pero es redundante.
cz

2

init () no devuelve ningún valor resuelto perfectamente

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)

salida: mi velocidad es de 21 kmh


-2

Bueno, si ya no le importa la instancia del objeto ... ¡puede reemplazarla!

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

print MuaHaHa('foo')=='foo'

2
Eso solo cambia lo que se asigna al nombre selfdentro de ese constructor.
Ondrej K.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.