¿Hay alguna diferencia entre llamar len([1,2,3])
o [1,2,3].__len__()
? Si no hay una diferencia visible, ¿qué se hace de forma diferente detrás de las escenas?diferencia entre len() y .__ len __()?
Respuesta
len
es una función para obtener la longitud de una colección. Funciona llamando al método __len__
de un objeto. __something__
atributos son especiales y generalmente más de lo que parece, y generalmente no se deben llamar directamente.
Se decidió en algún momento hace mucho tiempo que la longitud de algo debería ser una función y no un código de método, razonando que el significado de len(a)
sería claro para los principiantes, pero a.len()
no sería tan claro. Cuando Python comenzó __len__
ni siquiera existía y len
era algo especial que funcionaba con algunos tipos de objetos. Independientemente de si la situación que esto nos deja tiene sentido o no, está aquí para quedarse.
Está aquí para quedarse, pero no estaría de más tener un método 'some_collection.length()' además. En realidad, '.size()' sería mejor, porque las estructuras de datos basadas en árboles tienen un tamaño, pero no se representa fácilmente para tener una longitud. –
@EvgeniSergeev Y, de hecho, objetos como ese tienen tales atributos: una matriz numpy tiene un atributo 'forma' (que no es un método en absoluto, ya que es una propiedad del objeto, no una acción sobre el objeto). –
fwiw, una razón plausible para esto es que python _realmente really_ no le gusta reservar nombres de métodos - una clase 'Rectangle' podría querer tener' length' y 'width', y si' .length() 'se reservaron efectivamente, tendrías que cambiar el nombre torpemente o romper el tipado pato. – Eevee
Se puede pensar en len() por ser más o menos equivalente a
def len(x):
return x.__len__()
Una de las ventajas es que 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 enteros
>>> (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()
Supongo que te refieres a 'operator.methodcaller' en lugar de' operator.attrgetter'. – Elazar
@Elazar, sí, lo hice. gracias –
Es a menudo el caso de que el comportamiento "típico" de un built-in o el explotador es llamar (con diferentes y sintaxis mejor) adecuados métodos mágicos (queridos con nombres como __whatever__
) en los objetos involucrados. A menudo, el operador incorporado tiene "valor agregado" (es capaz de tomar diferentes caminos dependiendo de los objetos involucrados) - en el caso de len
contra __len__
, es solo un poco de cordura verificar en el built-in que falta del 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 a la len
incorporado, que está seguro de que, si el programa continúa después de que en lugar de lanzar una excepción, la llamada ha devuelto un número entero , no negativo, y menos de 2 ** 31 - cuando ve una llamada al xxx.__len__()
, no tiene certeza (excepto que el autor del código no está familiarizado con Python o no sirve para nada ;-).
Otros componentes incorporados proporcionan incluso más valor agregado más allá de simples controles de cordura y legibilidad. Al diseñar uniformemente todo el Python para que funcione a través de llamadas a builtins y 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 se produce un error: hasta 2.5, tuvo que llamar al foo.next()
- en 2.6, mientras que todavía funciona para la compatibilidad con versiones anteriores, debe llamar al next(foo)
, y en 3.*
, el método mágico se llama correctamente __next__
en lugar de "oops- ey "next
! -).
Por lo tanto, la regla general debe ser no llamar directamente a un método mágico (pero siempre indirectamente a través de un built-in) a menos que sepa exactamente por qué necesita hacerlo (p., cuando anula dicho método en una subclase, si la subclase debe diferir a la superclase, debe hacerlo mediante una llamada explícita al método mágico).
Soy un usuario principiante de Python (no el programador principiante pensado) y no estoy seguro de "Cuando veas una llamada a la len incorporada, estás seguro de que si el programa continúa después de eso en lugar de presentar una excepción ". Intenté esto: 'def len (x): \t return" I am a string. " print (len (42)) print (len ([1,2,3])) 'e imprimió' I am string' dos veces. ¿Puedes explicarlo más? –
@ DarekNędza Esto no tiene nada que ver con lo anterior, que se trata de la lenidad integrada. Usted acaba de definir su función len, que por supuesto puede devolver lo que quiera. OP habló sobre la lenidad incorporada, que llama a '__len__' special _method_ (no funciona) en el objeto bajo consideración. – Veky
@Veky ¿Cómo puedo estar seguro de que estoy llamando a la función incorporada 'len' no a alguna otra función (como en mi ejemplo) que pasó a tener el mismo nombre -' len'. No hay advertencia como "Estás redefiniendo función incorporada len" o algo como esto. En mi opinión, no puedo estar seguro de lo que dijo Alex en su respuesta. –
Puede comprobar Pythond docs:
>>> class Meta(type):
... def __getattribute__(*args):
... print "Metaclass getattribute invoked"
... return type.__getattribute__(*args)
...
>>> class C(object):
... __metaclass__ = Meta
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print "Class getattribute invoked"
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
- 1. Python, len y tamaño de ints
- 2. Python, len y sectores en cadenas Unicode
- 3. ¿Cuál es la diferencia entre list [-1:] [0] y list [len (list) -1]?
- 4. rango (len (lista)) o enumerar (enumerar)?
- 5. Rendimiento perfilado de len (conjunto) frente a conjunto .__ len __() en Python 3
- 6. C++ equivalente a la función Python len()?
- 7. len() Vs datalength() en sqlserver 2005
- 8. En python, ¿qué hace len (list)?
- 9. PCAP estructura pcap_pkthdr len vs Caplen
- 10. ¿Son Len (cell.Value) = 0 y cell.Value = "" equivalentes en Excel?
- 11. $ idx y $ len en un enunciado condicional dust.js
- 12. Comprensión de lista y len() vs. simple for loop
- 13. Los valores no definidos en Array inicializador (LEN)
- 14. Alternativa a 'para i en xrange (len (x))'
- 15. Diferencia entre [corchetes] y * asterisco
- 16. ¿Por qué no es la función 'len' heredada por los diccionarios y listas en Python
- 17. Diferencia entre cleaned_data y cleaned_data.get en Django
- 18. ¿Cuál es la diferencia entre equ y db en NASM?
- 19. ¿Cuál es la notación big-o para la función `len()` en Python?
- 20. ¿Cómo puedo generar permutaciones de longitud LEN dada una lista de N elementos?
- 21. ¿Por qué la función LEN() de t-sql ignora los espacios finales?
- 22. Las ventajas de tener una función estática como len(), max() y min() sobre llamadas al método heredado
- 23. ¿Rendimiento o diferencia de estilo entre "si" y "si no"?
- 24. MySQL: diferencia entre ', `,' y"
- 25. Diferencia entre. y #
- 26. Diferencia entre & y &
- 27. ¿Diferencia entre == y caso?
- 28. Diferencia entre objeto y *?
- 29. La diferencia entre $ * y $ @
- 30. VBA: Diferencia entre y y +
Ver http://stackoverflow.com/questions/496009/is-there-any-case-where-lensomeobj-does-not-call-someobjs-len- función/497096 # 497096 –