Saltar al contenido

¿Diferencia entre len () y .__ len __ ()?

Solución:

len es una función para obtener la longitud de una colección. Funciona llamando a un objeto __len__ método. __something__ los atributos son especiales y, por lo general, más de lo que se ve a simple vista y, por lo general, no deben llamarse directamente.

Se decidió en algún momento hace mucho tiempo que obtener la longitud de algo debería ser una función y no un código de método, razonando que len(a)El significado sería claro para los principiantes, pero a.len() no sería tan claro. Cuando comenzó Python __len__ ni siquiera existía y len era algo especial que funcionaba con algunos tipos de objetos. Ya sea que la situación que esto nos deja tenga total sentido o no, está aquí para quedarse.

A menudo ocurre que el comportamiento “típico” de un operador incorporado o es llamar (con una sintaxis diferente y más agradable) métodos mágicos adecuados (aquellos con nombres como __whatever__) en los objetos involucrados. A menudo, el operador integrado o tiene un “valor agregado” (es capaz de tomar diferentes caminos dependiendo de los objetos involucrados) – en el caso de len vs __len__, es solo un poco de verificación de cordura en el incorporado que falta en el método mágico:

>>> class bah(object):
...   def __len__(self): return "an inch"
... 
>>> bah().__len__()
'an inch'
>>> len(bah())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object cannot be interpreted as an integer

Cuando vea una llamada al len incorporado, eres seguro que, si el programa continúa después de eso en lugar de generar una excepción, la llamada ha devuelto un número entero, no negativo y <= sys.maxsize – cuando ve una llamada a xxx.__len__(), no tienes certeza (excepto que el autor del código no está familiarizado con Python o no es bueno ;-).

Otros componentes incorporados brindan aún más valor agregado más allá de las simples comprobaciones de cordura y legibilidad. Al diseñar uniformemente todo Python para que funcione a través de llamadas a incorporaciones y el uso de operadores, nunca a través de llamadas a métodos mágicos, los programadores se libran de la carga de recordar qué caso es cuál. (A veces aparece un error: hasta la 2.5, tenía que llamar foo.next() – en 2.6, aunque eso todavía funciona para la compatibilidad con versiones anteriores, debe llamar next(foo), y en 3.*, el método mágico tiene el nombre correcto __next__ en lugar del “oops-ey” next! -).

Entonces, la regla general debería ser nunca llamar a un método mágico directamente (pero siempre indirectamente a través de un método incorporado) a menos que sepa exactamente por qué necesita hacerlo (por ejemplo, cuando está anulando un método de este tipo en una subclase, si el subclase necesita diferir a la superclase que debe hacerse mediante una llamada explícita al método mágico).

Puede pensar que len () es aproximadamente equivalente a

def len(x):
    return x.__len__()

Una ventaja es que te permite escribir cosas como

somelist = [[1], [2, 3], [4, 5, 6]]
map(len, somelist) 

en lugar de

map(list.__len__, somelist)

o

map(operator.methodcaller('__len__'), somelist)

Sin embargo, hay un comportamiento ligeramente diferente. Por ejemplo en el caso de ints

>>> (1).__len__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__len__'
>>> len(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *