usar tutorial sirve sintaxis que programacion para lenguaje español desde como cero python magic-methods

tutorial - ¿Por qué Python usa ''métodos mágicos''?



sintaxis python (7)

AFAIK, len es especial a este respecto y tiene raíces históricas.

Aquí hay una cita de las preguntas frecuentes :

¿Por qué Python utiliza métodos para algunas funcionalidades (por ejemplo, list.index ()) pero funciones para otras (por ej. Len (list))?

La razón principal es la historia. Las funciones se usaron para aquellas operaciones que eran genéricas para un grupo de tipos y que estaban destinadas a funcionar incluso para objetos que no tenían ningún método (p. Ej., Tuplas). También es conveniente tener una función que se pueda aplicar fácilmente a una colección amorfa de objetos cuando se usan las características funcionales de Python (map (), apply () y otros).

De hecho, implementar len (), max (), min () como función incorporada es en realidad menos código que implementarlos como métodos para cada tipo. Uno puede objetar sobre casos individuales pero es parte de Python, y es demasiado tarde para hacer cambios tan fundamentales ahora. Las funciones deben permanecer para evitar la rotura masiva de código.

Los otros "métodos mágicos" (realmente llamados métodos especiales en el folklore de Python) tienen mucho sentido, y existe una funcionalidad similar en otros idiomas. En su mayoría se utilizan para el código que se llama implícitamente cuando se utiliza la sintaxis especial.

Por ejemplo:

  • operadores sobrecargados (existen en C ++ y otros)
  • constructor / destructor
  • ganchos para acceder a los atributos
  • herramientas para metaprogramación

y así...

He estado jugando con Python recientemente, y una cosa que encuentro un poco extraña es el uso extensivo de ''métodos mágicos'', por ejemplo, para hacer que su longitud esté disponible, un objeto implementa un método def __len__(self) y luego es llamado cuando escribe len(obj) .

Me preguntaba por qué los objetos no definen simplemente un método len(self) y lo llaman directamente como miembro del objeto, por ejemplo, obj.len() ? Estoy seguro de que debe haber buenas razones para que Python lo haga de la forma en que lo hace, pero como novato aún no he descubierto lo que son.


Algunas de estas funciones hacen más de lo que un único método sería capaz de implementar (sin métodos abstractos en una superclase). Por ejemplo, bool() actúa de esta manera:

def bool(obj): if hasattr(obj, ''__nonzero__''): return bool(obj.__nonzero__()) elif hasattr(obj, ''__len__''): if obj.__len__(): return True else: return False return True

También puede estar 100% seguro de que bool() siempre devolverá True o False; si confiabas en un método, no podías estar completamente seguro de lo que obtendrías.

Algunas otras funciones que tienen implementaciones relativamente complicadas (más complicadas que los métodos mágicos subyacentes probablemente) son iter() y cmp() , y todos los métodos de atributo ( getattr , setattr y delattr ). Las cosas como int también acceden a métodos mágicos cuando se hace coerción (puede implementar __int__ ), pero hacen doble función como tipos. len(obj) es en realidad el único caso en el que no creo que sea diferente de obj.__len__() .


Desde el Zen de Python:

En vista de la ambigüedad, rechace la tentación de adivinar.
Debería haber una, y preferiblemente solo una, forma obvia de hacerlo.

Esta es una de las razones: con los métodos personalizados, los desarrolladores serían libres de elegir un nombre de método diferente, como getLength() , length() , getlength() o lo que sea. Python impone el uso de nombres estrictos para que se pueda usar la función común len() .

Todas las operaciones que son comunes para muchos tipos de objetos se ponen en métodos mágicos, como __nonzero__ , __len__ o __repr__ . Sin embargo, en su mayoría son opcionales.

La sobrecarga del operador también se realiza con métodos mágicos (por ejemplo, __le__ ), por lo que tiene sentido usarlos para otras operaciones comunes, también.


No hay mucho que agregar a las dos publicaciones anteriores, pero todas las funciones "mágicas" en realidad no son mágicas. Son parte del módulo __builtins__ que se importa de forma implícita o automática cuando se inicia el intérprete. ES DECIR:

from __builtins__ import *

sucede cada vez antes de que comience su programa.

Siempre pensé que sería más correcto si Python solo hiciera esto para el shell interactivo, y requiriera scripts para importar las diversas partes de los builtins que necesitaban. También probablemente sea diferente __ main__ handling sería bueno en shells vs interactive. De todos modos, revisa todas las funciones y ve cómo es sin ellas:

dir (__builtins__) ... del __builtins__


No son realmente "nombres mágicos". Es solo la interfaz que un objeto debe implementar para proporcionar un servicio determinado. En este sentido, no son más mágicos que cualquier definición de interfaz predefinida que deba volver a implementar.


Python usa la palabra: - "Métodos Mágicos" porque esos métodos realmente hacen magia para tu programa. Una de las mayores ventajas de usar los métodos mágicos de Python es que proporcionan una forma simple de hacer que los objetos se comporten como tipos incorporados. Eso significa que puede evitar formas feas, contraintuitivas y no estándar de realizar operadores básicos.

Considera un ejemplo siguiente:

dict1 = {1 : "ABC"} dict2 = {2 : "EFG"} dict1 + dict2 Traceback (most recent call last): File "python", line 1, in <module> TypeError: unsupported operand type(s) for +: ''dict'' and ''dict''

Esto da un error, porque el tipo de diccionario no admite la adición. Ahora, ampliemos la clase del diccionario y agreguemos el método mágico "__add__" : -

class AddableDict(dict): def __add__(self, otherObj): self.update(otherObj) return AddableDict(self) dict1 = AddableDict({1 : "ABC"}) dict2 = AddableDict({2 : "EFG"}) print (dict1 + dict2)

Ahora, da la siguiente salida,

{1: ''ABC'', 2: ''EFG''}

Por lo tanto, al agregar este método, de repente sucedió la magia y el error que estaba recibiendo antes, se ha ido.

Espero, te aclara las cosas. Para obtener más información, consulte el enlace que se proporciona a continuación:

http://web.archive.org/web/20161024123835/http://www.rafekettler.com/magicmethods.html


Si bien la razón es principalmente histórica, hay algunas peculiaridades en el lenguaje de Python que hacen que el uso de una función en lugar de un método apropiado.

Algunas operaciones en Python se implementan como métodos, por ejemplo, list.index y dict.append , mientras que otras se implementan como callables y métodos mágicos, por ejemplo str y iter e reversed . Los dos grupos difieren lo suficiente por lo que el enfoque diferente está justificado:

  1. Ellos son comunes.
  2. str , int y friends son tipos. Tiene más sentido llamar al constructor.
  3. La implementación difiere de la llamada de función. Por ejemplo, iter podría llamar a __getitem__ si __iter__ no está disponible, y admite argumentos adicionales que no caben en una llamada de método. Por la misma razón it.next() ha sido cambiado a next(it) en versiones recientes de Python, tiene más sentido.
  4. Algunos de estos son parientes cercanos de los operadores. Hay sintaxis para llamar a __iter__ y __next__ - se llama el ciclo for . Para consistencia, una función es mejor. Y lo hace mejor para ciertas optimizaciones.
  5. Algunas de las funciones son simplemente demasiado similares al resto de alguna manera: repr actúa como str does. Tener str(x) versus x.repr() sería confuso.
  6. Algunos de ellos rara vez usan el método de implementación real, por ejemplo, isinstance .
  7. Algunos de ellos son operadores reales, getattr(x, ''a'') es otra forma de hacer xa y getattr comparte muchas de las cualidades antes mencionadas.

Personalmente llamo al primer grupo como método y al segundo grupo como operador. No es una distinción muy buena, pero espero que ayude de alguna manera.

Habiendo dicho esto, len no encaja exactamente en el segundo grupo. Está más cerca de las operaciones en la primera, con la única diferencia de que es mucho más común que casi ninguna de ellas. Pero lo único que hace es llamar a __len__ , y está muy cerca de L.index . Sin embargo, hay algunas diferencias. Por ejemplo, __len__ podría ser llamado para la implementación de otras características, como bool , si el método se llama len , podrías romper bool(x) con un método len personalizado que hace cosas completamente diferentes.

En resumen, tiene un conjunto de características muy comunes que las clases pueden implementar a las que se puede acceder a través de un operador, a través de una función especial (que generalmente hace más que la implementación, como lo haría un operador), durante la construcción del objeto, y todas ellas compartir algunos rasgos comunes Todo el resto es un método. Y len es algo así como una excepción a esa regla.