¿Por qué necesitas "auto"? en Python para referirse a las variables de instancia?

13

He estado programando en varios lenguajes como Java, Ruby, Haskell y Python. Tengo que cambiar entre muchos idiomas por día debido a los diferentes proyectos en los que trabajo. Ahora, el problema es que a menudo me olvido de escribir, selfya que el primer parámetro en las definiciones de funciones en Python es llamar a métodos en el mismo objeto.

Dicho esto, estoy bastante sorprendido por este enfoque de Python. Básicamente, tenemos que escribir más para hacer las cosas, en los lenguajes como Java y Ruby las cosas se simplifican al hacer referencia automática a las variables en el objeto actual.

Mi pregunta es ¿por qué es esto selfnecesario? ¿Es puramente una elección de estilo, o hay una razón por la cual Python no puede permitirte omitir selfla forma en que Java y C ++ te permiten omitir this?

vivek
fuente
lectura recomendada: ¿Cuál es el problema con "Pros y contras"?
mosquito
1
@gnat ahora solo es profesional, y en serio es una buena pregunta que me está molestando desde hace unos días, por favor, no la maten votando en contra.
vivek
2
Esta pregunta ha sido más que completamente cubierta por stackoverflow.com/questions/2709821/… .
David Arno
Tengo entendido que se basa en el estilo C de pasar un puntero a una estructura como primer argumento.
Dannnno
Escribir @staticmethodantes de la declaración del método, suprime el error (solo para información y tampoco recomendado)
Yash

Respuestas:

23

1) ¿Por qué se selfrequiere como parámetro explícito en las firmas de métodos?

Porque los métodos son funciones y foo.bar(baz)solo es azúcar sintáctica bar(foo, baz). Las clases son solo diccionarios donde algunos de los valores son funciones. (Los constructores también son solo funciones, por lo que Python no necesita new). Puede decir que Python hace explícito que los objetos se crean a partir de componentes más simples. Esto está de acuerdo con la filosofía "explícito es mejor que implícito".

En contraste, en Java los objetos son realmente mágicos y no pueden reducirse a componentes más simples en el lenguaje. En Java (al menos hasta Java 8), una función siempre es un método propiedad de un objeto, y esta propiedad no se puede cambiar debido a la naturaleza estática del lenguaje. Por lo tanto, no hay ambigüedad sobre lo que se thisrefiere, por lo que tiene sentido tenerlo implícitamente definido.

JavaScript es un ejemplo de un lenguaje que tiene un lenguaje implícito thiscomo Java, pero donde las funciones pueden existir por separado de los objetos como en Python. Esto lleva a mucha confusión sobre lo que se thisrefiere a cuando las funciones se pasan y se llaman en diferentes contextos. Muchos piensan instintivamente que thisdeben referirse a alguna propiedad intrínseca de la función, mientras que en realidad está puramente determinada por la forma en que se llama a la función. Creo que tener thisun parámetro explícito como en Python haría esto mucho menos confuso.

Algunos otros beneficios del selfparámetro explícito :

  • Los decoradores son solo funciones que envuelven otras funciones. Como los métodos son solo funciones, los decoradores funcionan igual de bien en los métodos. Si hubiera algún tipo de yo implícito, los decoradores no funcionarían de manera transparente en los métodos.

  • Los métodos de clase y los métodos estáticos no toman un parámetro de instancia. Los métodos de clase toman una clase como primer argumento (típicamente llamado cls). El explícito selfo los clsparámetros aclaran mucho más lo que está sucediendo y a qué tiene acceso en el método.

2) ¿Por qué las variables de instancias siempre deben calificarse con " self.?

En Java, no necesita prefijar las variables miembro con " this.", pero en Python " self." siempre es necesario. La razón es que Python no tiene una sintaxis explícita para declarar variables, por lo que no habría forma de saber si x = 7se supone que debe declarar una nueva variable local o asignarla a una variable miembro. Especificar self.resuelve esta ambigüedad.

JacquesB
fuente
La referencia de variable de miembro implícita (sin self., como Java) es fundamentalmente incompatible con las reglas de alcance y cuando necesita ser explícito allí, ser implícito sobre el parámetro ya no tiene tanto sentido.
Jan Hudec
@ JanHudec: Bien, punto. Lo he agregado a la respuesta.
JacquesB
6

Hay una razón bastante simple por la que AFAIK realmente no se ha tratado en el duplicado entre sitios, ni aquí: Python comenzó como un lenguaje de procedimiento. Se basó en ABC, también un lenguaje de procedimiento.

La orientación a objetos se agregó más tarde, y cuando se agregó, Guido van Rossum quería agregar la cantidad mínima de características posibles, para mantener el diseño de Python simple. Python ya tenía dicts y funciones, entonces, ¿por qué agregar algo completamente nuevo al lenguaje, cuando un objeto puede ser simplemente una dictde las ranuras y una clase puede ser simplemente una dictde las funciones? Un método puede interpretarse como una función parcialmente aplicada que se cierra sobre un único argumento distinguido. Y así es precisamente cómo se implementan los métodos en Python: no lo son. Son solo funciones que reciben un argumento distinguido adicional.

Jörg W Mittag
fuente
Creo que Python era compatible con OO y tenía clases y herencia de la primera versión lanzada. Al menos esto es lo que Wikipedia me dice. Pero el proceso de van Rossums en el diseño inicial del lenguaje podría haber sido como usted describe.
JacquesB
Gracias por el enlace, esta es una lectura realmente interesante.
JacquesB
2

Aquí están mis conclusiones basadas en las respuestas anteriores y leyendo las divagaciones de Guido sobre este tema:

La gran idea

Las funciones son los bloques de construcción importantes en Python (o deberíamos decir el único), de hecho, estamos emulando a OOP mediante el uso de funciones.

Dado que una clase no es más que un diccionario de funciones, podemos adjuntar cualquier función a cualquier clase en tiempo de ejecución. Básicamente, debido a esta necesidad de utilizar las funciones en tiempo de ejecución, podemos hacer cosas como Monkey Patching . Aquí el selfparámetro que soporta el polimorfismo paramétrico.

vivek
fuente
1
Se alientan las preguntas con respuesta propia cuando su respuesta es de alta calidad. Cuando comparo su respuesta aquí con las otras respuestas, me pregunto por qué sintió que necesitaba agregar esto. Las otras respuestas profundizan más y agregan más detalles que lo que hace su respuesta.
1
@ GlenH7 la respuesta fue solo para mi referencia porque cada vez que no puedo ir y leer la respuesta de todos una y otra vez. En cuanto a la calidad, dígame si alguna información es engañosa. De todos modos, generalmente espero 2-3 días para aceptar cualquier respuesta.
vivek
El voto negativo se está convirtiendo en una moneda barata y todos aquí lo están gastando con ambas manos sin saber su significado. ¿Te das cuenta de que si alguien viene aquí, verás que esta respuesta rechazada supondrá que está mal?
vivek