lenguaje - python tutorial
¿Por qué necesita explícitamente tener el argumento "self" en un método de Python? (8)
Creo que la razón real además de "El Zen de Python" es que las Funciones son ciudadanos de primera clase en Python.
Lo que esencialmente los convierte en un Objeto. Ahora La cuestión fundamental es si sus funciones también son un objeto, en el paradigma orientado a Objetos, ¿cómo enviaría mensajes a Objetos cuando los mismos mensajes son objetos?
Parece un problema con el huevo de gallina, para reducir esta paradoja, la única forma posible es pasar un contexto de ejecución a métodos o detectarlo. Pero dado que python puede tener funciones anidadas, sería imposible hacerlo ya que el contexto de ejecución cambiaría para las funciones internas.
Esto significa que la única solución posible es pasar explícitamente ''self'' (El contexto de ejecución).
Entonces, creo que es un problema de implementación, el Zen vino mucho más tarde.
Al definir un método en una clase en Python, se ve algo como esto:
class MyClass(object):
def __init__(self, x, y):
self.x = x
self.y = y
Pero en algunos otros lenguajes, como C #, tiene una referencia al objeto al que está vinculado el método con la palabra clave "this" sin declararlo como un argumento en el prototipo del método.
¿Fue esta una decisión de diseño de lenguaje intencional en Python o hay algunos detalles de implementación que requieren el paso de "self" como argumento?
Creo que tiene que ver con PEP 227:
Los nombres en el alcance de clase no son accesibles. Los nombres se resuelven en el alcance de la función circundante más interna. Si se produce una definición de clase en una cadena de ámbitos anidados, el proceso de resolución omite las definiciones de clase. Esta regla evita las interacciones impares entre los atributos de clase y el acceso variable local. Si se produce una operación de vinculación de nombre en una definición de clase, crea un atributo en el objeto de clase resultante. Para acceder a esta variable en un método, o en una función anidada dentro de un método, se debe usar una referencia de atributo, ya sea a través de uno mismo o mediante el nombre de clase.
Es para minimizar la diferencia entre métodos y funciones. Le permite generar fácilmente métodos en metaclases, o agregar métodos en tiempo de ejecución a clases preexistentes.
p.ej
>>> class C(object):
... def foo(self):
... print "Hi!"
...
>>>
>>> def bar(self):
... print "Bork bork bork!"
...
>>>
>>> c = C()
>>> C.bar = bar
>>> c.bar()
Bork bork bork!
>>> c.foo()
Hi!
>>>
También (hasta donde sé) facilita la implementación del tiempo de ejecución de Python.
Me gusta citar el Zen de Python de Peters. "Explícito es mejor que implícito".
En Java y C ++, '' this.
''se puede deducir, excepto cuando tienes nombres de variables que hacen imposible deducirlos. Entonces a veces lo necesitas y otras veces no.
Python elige hacer que cosas como esta sean explícitas en lugar de basadas en una regla.
Además, dado que nada es implícito o asumido, partes de la implementación están expuestas. self.__class__
, self.__dict__
y otras estructuras "internas" están disponibles de una manera obvia.
Python no lo obliga a usar "self". Puedes darle el nombre que quieras. Solo tiene que recordar que el primer argumento en un encabezado de definición de método es una referencia al objeto.
Sugiero que uno lea el blog de Guido van Rossum sobre este tema: por qué el yo explícito debe permanecer .
Cuando se decora una definición de método, no sabemos si darle automáticamente un parámetro ''self'' o no: el decorador podría convertir la función en un método estático (que no tiene ''self''), o un método de clase (que tiene un tipo de self gracioso que se refiere a una clase en lugar de una instancia), o podría hacer algo completamente diferente (es trivial escribir un decorador que implemente ''@classmethod'' o ''@staticmethod'' en Python puro). No hay forma de saber qué hace el decorador si desea dotar al método que se define con un argumento ''propio'' implícito o no.
Rechazo hacks como special-casing ''@classmethod'' y ''@staticmethod''.
También hay otra respuesta muy simple: según el zen de python , "explícito es mejor que implícito".
También le permite hacer esto: (en resumen, invocar Outer(3).create_inner_class(4)().weird_sum_with_closure_scope(5)
devolverá 12, pero lo hará de la manera más loca.
class Outer(object):
def __init__(self, outer_num):
self.outer_num = outer_num
def create_inner_class(outer_self, inner_arg):
class Inner(object):
inner_arg = inner_arg
def weird_sum_with_closure_scope(inner_self, num)
return num + outer_self.outer_num + inner_arg
return Inner
Por supuesto, esto es más difícil de imaginar en lenguajes como Java y C #. Al hacer que la autoreferencia sea explícita, puede consultar cualquier objeto mediante esa referencia automática. Además, tal forma de jugar con clases en tiempo de ejecución es más difícil de hacer en los lenguajes más estáticos, no es que sea necesariamente bueno o malo. Es solo que el yo explícito permite que toda esta locura exista.
Además, imagine esto: quisiéramos personalizar el comportamiento de los métodos (para crear perfiles, o alguna loca magia negra). Esto puede llevarnos a pensar: ¿y si tuviéramos un Method
clase cuyo comportamiento pudiéramos anular o controlar?
Bueno, aquí está:
from functools import partial
class MagicMethod(object):
"""Does black magic when called"""
def __get__(self, obj, obj_type):
# This binds the <other> class instance to the <innocent_self> parameter
# of the method MagicMethod.invoke
return partial(self.invoke, obj)
def invoke(magic_self, innocent_self, *args, **kwargs):
# do black magic here
...
print magic_self, innocent_self, args, kwargs
class InnocentClass(object):
magic_method = MagicMethod()
Y ahora: InnocentClass().magic_method()
actuará como se espera. El método se vinculará con el parámetro innocent_self
a InnocentClass
y con magic_self
a la instancia de MagicMethod. ¿Extraño eh? Es como tener 2 palabras clave this1
y this2
en idiomas como Java y C #. Magia como esta permite a los frameworks hacer cosas que de otra manera serían mucho más detalladas.
Una vez más, no quiero comentar sobre la ética de estas cosas. Solo quería mostrar cosas que serían más difíciles de hacer sin una auto referencia explícita.