¿Qué hacen __init__ y self en Python?

796

Estoy aprendiendo el lenguaje de programación Python y me encontré con algo que no entiendo completamente.

En un método como:

def method(self, blah):
    def __init__(?):
        ....
    ....

¿Qué selfhacer? ¿Qué se supone que es? ¿Es obligatorio?

¿Qué hace el __init__método? ¿Por qué es necesario? (etc.)

Creo que podrían ser construcciones de OOP, pero no sé mucho.

ivanleoncz
fuente

Respuestas:

585

En este código:

class A(object):
    def __init__(self):
        self.x = 'Hello'

    def method_a(self, foo):
        print self.x + ' ' + foo

... la selfvariable representa la instancia del objeto en sí. La mayoría de los lenguajes orientados a objetos pasan esto como un parámetro oculto a los métodos definidos en un objeto; Python no lo hace. Tienes que declararlo explícitamente. Cuando crea una instancia de la Aclase y llama a sus métodos, se pasará automáticamente, como en ...

a = A()               # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument

El __init__método es aproximadamente lo que representa un constructor en Python. Cuando llama a A()Python, crea un objeto para usted y lo pasa como el primer parámetro al __init__método. Cualquier parámetro adicional (p. Ej. A(24, 'Hello')) También se pasará como argumento, en este caso , se generará una excepción, ya que el constructor no los espera.

Chris B.
fuente
8
¿Qué pasa si pones x = 'Hello'fuera de init pero dentro de la clase? ¿Es como Java donde es lo mismo, o se convierte en una variable estática que solo se inicializa una vez?
Jayen
15
Es como una variable estática. Solo se inicializa una vez y está disponible a través de A.xo a.x. Tenga en cuenta que anularlo en una clase específica no afectará la base, por lo que A.x = 'foo'; a.x = 'bar'; print a.x; print A.xse imprimirá barentoncesfoo
Chris B.
156
Vale la pena señalar que el primer argumento no necesariamente debe llamarse self, solo es por convención.
Henry Gomersall
13
¿Para qué sirve objectla declaración de clase? He notado que algunas clases tienen esto y otras no
Chris
99
@Chris Es por compatibilidad con Python 2. En Python 3 no hay necesidad de heredar explícitamente objectporque sucede de manera predeterminada.
Gabriel
241

Sí, tienes razón, estas son construcciones oop.

__init__es el constructor de una clase. El selfparámetro se refiere a la instancia del objeto (como thisen C ++).

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

los __init__ llama al método cuando se asigna memoria para el objeto:

x = Point(1,2)

Es importante usar el self parámetro dentro del método de un objeto si desea conservar el valor con el objeto. Si, por ejemplo, implementa el __init__método de esta manera:

class Point:
    def __init__(self, x, y):
        _x = x
        _y = y

Sus parámetros xy yse almacenarán en variables en la pila y se descartarán cuando el método init salga del alcance. Establecer esas variables como self._xy self._yestablece esas variables como miembros del Pointobjeto (accesible durante la vida útil del objeto).

RedBlueThing
fuente
1
Entonces, ¿hay alguna razón por la que no quieras selfestar en el constructor? ¿Por qué incluso tiene que especificarlo, no sería mejor si fuera implícito?
Aaron Franke
Hasta donde sé, __ init __ no es un constructor, es el primer método que se ejecutará cuando se cree cualquier objeto, __ init __ se usa para configurar el objeto. __ new __ es el constructor en python.
Deepanshu el
207

Un breve ejemplo ilustrativo.

Con la esperanza de que pueda ayudar un poco, aquí hay un ejemplo simple que utilicé para entender la diferencia entre una variable declarada dentro de una clase y una variable declarada dentro de una __init__función:

class MyClass(object):
    i = 123
    def __init__(self):
        self.i = 345

a = MyClass()
print(a.i)
print(MyClass.i)

Salida:

345
123
Dave Everitt
fuente
77
Observación interesante, pero creo que estás en el camino equivocado. Con print MyClass.i parece que estás llamando a una variable 'estática' i. Donde como con ai estás llamando a una variable miembro, i. Me parece que init es solo un constructor que se ejecuta por primera vez cuando creas un objeto de la clase.
captainspi
34
Eso es lo que estaba tratando de 'explicarme a mí mismo' con este ejemplo: que la variable establecida __init__es lo que se pasa a las instancias de la clase, no la variable 'estática' de la clase en sí que tiene el mismo nombre ...
Dave Everitt
44

En breve:

  1. selfcomo sugiere, se refiere a sí mismo , el objeto que ha llamado el método. Es decir, si tiene N objetos que llaman al método, self.ase referirá a una instancia separada de la variable para cada uno de los N objetos. Imagina N copias de la variablea para cada objeto
  2. __init__es lo que se llama como constructor en otros lenguajes OOP como C ++ / Java. La idea básica es que es un método especial que se llama automáticamente cuando se crea un objeto de esa clase
Acumenus
fuente
29

__init__actúa como un constructor Deberá pasar "self" a cualquier función de clase como primer argumento si desea que se comporten como métodos no estáticos. "self" son variables de instancia para su clase.

paseo
fuente
1
'self' define si un método es estático o no. Wow, eso es una revelación para este chico de Java.
liwevire
25

Prueba este código. Espero que ayude a muchos programadores de C como yo a aprender Py.

#! /usr/bin/python2

class Person:

    '''Doc - Inside Class '''

    def __init__(self, name):
        '''Doc - __init__ Constructor'''
        self.n_name = name        

    def show(self, n1, n2):
        '''Doc - Inside Show'''
        print self.n_name
        print 'Sum = ', (n1 + n2)

    def __del__(self):
        print 'Destructor Deleting object - ', self.n_name

p=Person('Jay')
p.show(2, 3)
print p.__doc__
print p.__init__.__doc__
print p.show.__doc__

Salida:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay

Jayzcode
fuente
No sé si soy solo yo, pero leer este código fue un poco confuso. Tal vez sea porque todavía soy un programador principiante de Python, idk.
Linny
No tengo claro lo del documento ... ¿saca la documentación? y si hago: '' 'test - my doc' '', ¿puedo usar: print.p .__ test__? o es doc una palabra clave específica?
Thomas
@Thomas doc es la palabra clave para detalles documentados. Las comillas triples se utilizan para escribir documentos y el documento es una entidad opcional.
Jayzcode
25

Los objetos de clase admiten dos tipos de operaciones: referencias de atributos e instanciación

Las referencias de atributos utilizan la sintaxis estándar utilizada para todas las referencias de atributos en Python: obj.name. Los nombres de atributo válidos son todos los nombres que estaban en el espacio de nombres de la clase cuando se creó el objeto de clase. Entonces, si la definición de clase se ve así:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

entonces MyClass.iy MyClass.fson referencias de atributo válidas, que devuelven un entero y un objeto de función, respectivamente. Los atributos de clase también se pueden asignar a, por lo que puede cambiar el valor de MyClass.ipor asignación. __doc__también es un atributo válido, que devuelve la cadena de documentación perteneciente a la clase: "Una clase de ejemplo simple".

La instanciación de clase utiliza la notación de función. Simplemente imagine que el objeto de clase es una función sin parámetros que devuelve una nueva instancia de la clase. Por ejemplo:

x = MyClass()

La operación de instanciación ("llamar" a un objeto de clase) crea un objeto vacío. A muchas clases les gusta crear objetos con instancias personalizadas para un estado inicial específico. Por lo tanto, una clase puede definir un método especial llamado __init__(), como este:

def __init__(self):
    self.data = []

Cuando una clase define un __init__()método, la instanciación de clase se invoca automáticamente __init__()para la instancia de clase recién creada. Entonces, en este ejemplo, se puede obtener una nueva instancia inicializada:

x = MyClass()

Por supuesto, el __init__()método puede tener argumentos para una mayor flexibilidad. En ese caso, los argumentos dados al operador de instanciación de clase se pasan a __init__(). Por ejemplo,

class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart

x = Complex(3.0, -4.5)
x.r, x.i

Tomado de la documentación oficial que más me ayudó al final.


Aqui esta mi ejemplo

class Bill():
    def __init__(self,apples,figs,dates):
        self.apples = apples
        self.figs = figs
        self.dates = dates
        self.bill = apples + figs + dates
        print ("Buy",self.apples,"apples", self.figs,"figs 
                and",self.dates,"dates. 
                Total fruitty bill is",self.bill," pieces of fruit :)")

Cuando crea una instancia de clase Bill:

purchase = Bill(5,6,7)

Usted obtiene:

> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
> fruit :)
Harvey
fuente
22

Tuve problemas para entender esto yo mismo. Incluso después de leer las respuestas aquí.

Para comprender correctamente el __init__método, necesita comprenderse a sí mismo.

El autoparámetro

Los argumentos aceptados por el __init__método son:

def __init__(self, arg1, arg2):

Pero en realidad solo le pasamos dos argumentos:

instance = OurClass('arg1', 'arg2')

¿De dónde viene el argumento extra?

Cuando accedemos a los atributos de un objeto, lo hacemos por nombre (o por referencia). Aquí la instancia es una referencia a nuestro nuevo objeto. Accedemos al método printargs del objeto de instancia usando instance.printargs.

Para acceder a los atributos del objeto desde el __init__método, necesitamos una referencia al objeto.

Cada vez que se llama a un método, se pasa una referencia al objeto principal como primer argumento. Por convención, siempre llamas a este primer argumento tus métodos.

Esto significa en el __init__método que podemos hacer:

self.arg1 = arg1
self.arg2 = arg2

Aquí estamos estableciendo atributos en el objeto. Puede verificar esto haciendo lo siguiente:

instance = OurClass('arg1', 'arg2')
print instance.arg1
arg1

valores como este se conocen como atributos de objeto. Aquí el __init__método establece los atributos arg1 y arg2 de la instancia.

fuente: http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method

eee
fuente
17

tenga en cuenta que en selfrealidad podría ser cualquier identificador válido de Python. Por ejemplo, podríamos escribir con la misma facilidad, a partir del ejemplo de Chris B:

class A(object):
    def __init__(foo):
        foo.x = 'Hello'

    def method_a(bar, foo):
        print bar.x + ' ' + foo

y funcionaría exactamente igual. Sin embargo, se recomienda usar self porque otros pythoners lo reconocerán más fácilmente.

SingleNegationElimination
fuente
Estoy de acuerdo en que se recomendaría self en lugar de foo, ayuda a otros programadores a mirar el código
Linny
15

Básicamente, debe usar la palabra clave 'self' cuando usa una variable en múltiples funciones dentro de la misma clase. En cuanto a init , se usa para configurar valores predeterminados en caso de que no se invoquen otras funciones dentro de esa clase.

usuario1675111
fuente
66
No hay una palabra clave 'self' en Python. Llamar al primer parámetro 'self' es simplemente una convención.
David Anderson el
self se usa básicamente como marcador de posición. No es necesario que use uno mismo, puede usar "eeee" o "foo" o algo más, solo se recomienda para otros programadores mientras lee su código
Linny
15
  1. __init__es básicamente una función que "inicializará" / "activará" las propiedades de la clase para un objeto específico, una vez creado y emparejado con la clase correspondiente.
  2. self representa ese objeto que heredará esas propiedades.
atlas
fuente
1
la palabra clave "self" no tiene que usarse, es solo un marcador de posición. Puede usar cualquier palabra, pero se recomienda que se use a sí mismo para ayudar a la legibilidad del programa
Linny
13

El 'self' es una referencia a la instancia de clase

class foo:
    def bar(self):
            print "hi"

Ahora podemos crear una instancia de foo y llamar al método en él, Python agrega el parámetro self en este caso:

f = foo()
f.bar()

Pero también se puede pasar si la llamada al método no está en el contexto de una instancia de la clase, el siguiente código hace lo mismo

f = foo()
foo.bar(f)

Curiosamente, el nombre variable 'self' es solo una convención. La siguiente definición funcionará exactamente igual. Habiendo dicho que es una convención muy fuerte que debe seguirse siempre , pero sí dice algo sobre la naturaleza flexible del lenguaje.

class foo:
    def bar(s):
            print "hi"
tarn
fuente
¿Por qué dice eso algo sobre la naturaleza flexible del lenguaje? Simplemente dice que puede dar a las variables cualquier nombre legal que elija. ¿Cómo es eso diferente de cualquier otro lenguaje de programación?
Daniel
Como escribí en mi respuesta "bar" es solo una función en la que se proporciona una instancia de clase como primer parámetro. Entonces, aunque "bar" se define como un método vinculado a "foo", también podría llamarse con una instancia de alguna otra clase. No es así como funcionan los métodos y "esto" en Java, por ejemplo, aunque imagino que ve que estos son el mismo concepto, funciones y algún contexto de instancia (el contexto de instancia es el primer parámetro en Python y "this" en Java ") ¿Quizás ahora pueda ver la flexibilidad del lenguaje al que me refería?
Tarn
Sí, eso muestra la flexibilidad del lenguaje. La forma en que redactó su respuesta, parecía que estaba diciendo que el hecho de que podría llamar a la variable "self" algo más (como s) estaba mostrando la flexibilidad de python.
Daniel
12

Solo una demostración de la pregunta.

class MyClass:

    def __init__(self):
        print('__init__ is the constructor for a class')

    def __del__(self):
        print('__del__ is the destructor for a class')

    def __enter__(self):
        print('__enter__ is for context manager')
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__ is for context manager')

    def greeting(self):
        print('hello python')


if __name__ == '__main__':
    with MyClass() as mycls:
        mycls.greeting()

$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class
depurar
fuente
11

En este código:

class Cat:
    def __init__(self, name):
        self.name = name
    def info(self):
        print 'I am a cat and I am called', self.name

Aquí __init__actúa como un constructor de la clase y cuando se crea una instancia de un objeto, se llama a esta función.selfrepresenta el objeto de instanciación.

c = Cat('Kitty')
c.info()

El resultado de las declaraciones anteriores será el siguiente:

I am a cat and I am called Kitty
Anagha
fuente
11

¿Qué hace el yo ? ¿Qué se supone que es? ¿Es obligatorio ?

El primer argumento de cada método de clase, incluido init, siempre es una referencia a la instancia actual de la clase . Por convención, este argumento siempre se nombra self. En el método init, se selfrefiere al objeto recién creado; en otros métodos de clase, se refiere a la instancia cuyo método fue llamado.

Python no te obliga a usar " self ". Puedes darle el nombre que quieras. Pero recuerde que el primer argumento en la definición de un método es una referencia al objeto . Python agrega el selfargumento a la lista por usted; no necesita incluirlo cuando llame a los métodos. si no proporcionó el método self en init, obtendrá un error

TypeError: __init___() takes no arguments (1 given)

¿Qué hace el método init ? ¿Por qué es necesario? (etc.)

inites la abreviatura de inicialización. Es un constructor que se llama cuando realiza una instancia de la clase y no es necesario . Pero por lo general, nuestra práctica es escribir un método init para establecer el estado predeterminado del objeto. Si no está dispuesto a establecer ningún estado del objeto inicialmente, entonces no necesita escribir este método.

Muhammad Faizan Khan
fuente
8
# Source: Class and Instance Variables
# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables

class MyClass(object):
    # class variable
    my_CLS_var = 10

    # sets "init'ial" state to objects/instances, use self argument
    def __init__(self):
        # self usage => instance variable (per object)
        self.my_OBJ_var = 15

        # also possible, class name is used => init class variable
        MyClass.my_CLS_var = 20


def run_example_func():
    # PRINTS    10    (class variable)
    print MyClass.my_CLS_var

    # executes __init__ for obj1 instance
    # NOTE: __init__ changes class variable above
    obj1 = MyClass()

    # PRINTS    15    (instance variable)
    print obj1.my_OBJ_var

    # PRINTS    20    (class variable, changed value)
    print MyClass.my_CLS_var


run_example_func()
Manohar Reddy Poreddy
fuente
5

Python __init__yself qué hacen?

Que hace self hacer? ¿Qué se supone que es? ¿Es obligatorio?

¿Qué hace el __init__método? ¿Por qué es necesario? (etc.)

El ejemplo dado no es correcto, así que permítame crear un ejemplo correcto basado en él:

class SomeObject(object):

    def __init__(self, blah):
        self.blah = blah

    def method(self):
        return self.blah 

Cuando creamos una instancia del objeto, __init__se llama para personalizar el objeto después de que se haya creado. Es decir, cuando llamamos SomeObjecta 'blah'continuación (que podría ser cualquier cosa), se pasa a la __init__función como argumento blah:

an_object = SomeObject('blah')

El selfargumento es la instancia de SomeObjectque se asignará aan_object .

Más tarde, podríamos querer llamar a un método en este objeto:

an_object.method()

Haciendo la búsqueda punteada, es decir, an_object.method vincula la instancia a una instancia de la función, y el método (como se llamó anteriormente) ahora es un método "vinculado", lo que significa que no necesitamos pasar explícitamente la instancia a la llamada al método .

La llamada al método obtiene la instancia porque estaba vinculada en la búsqueda punteada y, cuando se llama, ejecuta el código que estaba programado para realizar.

El selfargumento implícitamente pasado se llama selfpor convención. Podríamos usar cualquier otro nombre legal de Python, pero es probable que otros programadores de Python lo asfixien y lo arruinen si lo cambia por otra cosa.

__init__es un método especial, documentado en la documentación del modelo de datos de Python . Se llama inmediatamente después de que se crea la instancia (generalmente a través de __new__, aunque __new__no es necesario a menos que esté subclasificando un tipo de datos inmutable).

Aaron Hall
fuente
3

Aquí, el chico ha escrito bastante bien y simple: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/

Lea el enlace de arriba como referencia a esto:

self? Entonces, ¿qué pasa con ese autoparámetro para todos los métodos del Cliente? ¿Qué es? ¡Por qué, es la instancia, por supuesto! Dicho de otra manera, un método como retirar define las instrucciones para retirar dinero de la cuenta de un cliente abstracto. Llamar a jeff.withdraw (100.0) pone esas instrucciones para usar en la instancia de jeff.

Entonces, cuando decimos retiro de fondos (auto, cantidad): estamos diciendo, "así es como retira dinero de un objeto de Cliente (que llamaremos auto) y una cifra en dólares (que llamaremos cantidad). es la instancia del Cliente que está retirando. No es mi caso hacer analogías tampoco. jeff.withdraw (100.0) es solo una abreviatura de Customer.withdraw (jeff, 100.0), que es perfectamente válido (si no se ve a menudo) código.

init self puede tener sentido para otros métodos, pero ¿qué pasa con init ? Cuando llamamos a init , estamos en el proceso de crear un objeto, entonces, ¿cómo puede haber un yo? Python nos permite extender el patrón propio cuando los objetos también se construyen, a pesar de que no encaja exactamente. Solo imagine que jeff = Customer ('Jeff Knupp', 1000.0) es lo mismo que llamar a jeff = Customer (jeff, 'Jeff Knupp', 1000.0); el jeff que pasó también se hizo el resultado.

Es por eso que cuando llamamos a init , inicializamos objetos diciendo cosas como self.name = name. Recuerde, dado que self es la instancia, esto equivale a decir jeff.name = name, que es lo mismo que jeff.name = 'Jeff Knupp. Del mismo modo, self.balance = balance es lo mismo que jeff.balance = 1000.0. Después de estas dos líneas, consideramos que el objeto Cliente está "inicializado" y listo para usar.

Ten cuidado con lo que __init__

Después de que init haya finalizado, la persona que llama puede asumir con razón que el objeto está listo para usar. Es decir, después de jeff = Customer ('Jeff Knupp', 1000.0), podemos comenzar a hacer depósitos y retirar llamadas en jeff; Jeff es un objeto completamente inicializado.

Laxmikant
fuente