Pregunta

Sé que python tiene una función len () que se usa para determinar el tamaño de una cadena, pero me preguntaba por qué no es un método del objeto de cadena.

Actualización

Ok, me di cuenta de que estaba equivocadamente avergonzada. __len __ () es en realidad un método de un objeto de cadena. Parece extraño ver código orientado a objetos en Python utilizando la función len en objetos de cadena. Además, también es raro ver a __len__ como nombre en lugar de solo len.

¿Fue útil?

Solución

Las cadenas tienen un método de longitud: __len__()

El protocolo en Python es implementar este método en objetos que tienen una longitud y usar el len () , que lo llama para usted, similar a la forma en que implementaría __iter __ () y use la función iter () incorporada (o haga que el método se le llame entre bambalinas) en objetos que sean iterables.

Consulte Emulación de tipos de contenedores para obtener más información.

Aquí hay una buena lectura sobre el tema de los protocolos en Python: Python y el principio de menos asombro

Otros consejos

La respuesta de Jim a esta pregunta puede ayudar; Lo copio aquí. Citando a Guido van Rossum:

  

En primer lugar, elegí len (x) sobre x.len () por razones de HCI (def __len __ () llegó mucho más tarde). Hay dos razones entrelazadas en realidad, ambas HCI:

     

(a) Para algunas operaciones, la notación de prefijo se lee mejor que postfix & # 8212; Las operaciones de prefijo (e infijo) tienen una larga tradición matemática que le gusta las anotaciones donde las imágenes ayudan al matemático a pensar en un problema. Compara la facilidad con la que reescribimos una fórmula como x * (a + b) en x a + x b con la torpeza de hacer lo mismo con una notación OO sin formato.

     

(b) Cuando leo el código que dice len (x), sé que está preguntando por la longitud de algo. Esto me dice dos cosas: el resultado es un entero y el argumento es una especie de contenedor. Por el contrario, cuando leo x.len (), ya tengo que saber que x es un tipo de contenedor que implementa una interfaz o hereda de una clase que tiene un len estándar (). Observe la confusión que ocasionalmente tenemos cuando una clase que no está implementando un mapeo tiene un método get () o keys (), o algo que no es & # 8217; t un archivo tiene un método write ().

     

Al decir lo mismo de otra manera, veo & # 8216; len & # 8216; como una operación incorporada. Odiaría perder eso. / & # 8230; /

Hay un método len :

>>> a = 'a string of some length'
>>> a.__len__()
23
>>> a.__len__
<method-wrapper '__len__' of str object at 0x02005650>

Python es un lenguaje de programación pragmático, y las razones para que len () sea una función y no un método de str , list , dict etc. son pragmáticos.

La función incorporada len () trata directamente con los tipos incorporados: la implementación CPython de len () en realidad devuelve el valor de ob_size en el campo PyVarObject C struct que representa cualquier objeto incorporado de tamaño variable en la memoria. Esto es mucho más rápido que llamar a un método, no es necesario que se realicen búsquedas de atributos. Obtener el número de elementos en una colección es una operación común y debe funcionar de manera eficiente para tipos básicos y diversos como str , list , array.array etc.

Sin embargo, para promover la coherencia, al aplicar len (o) a un tipo definido por el usuario, Python llama a o .__ len __ () como una alternativa. __len__ , __abs__ y todos los demás métodos especiales documentados en la El modelo de datos de Python facilita la creación de objetos que se comportan como los elementos integrados, habilitando las API expresivas y altamente consistentes que llamamos "pitón".

Al implementar métodos especiales, sus objetos pueden admitir iteración, sobrecargar operadores de infijo, administrar contextos en with etc. Puede pensar en el modelo de datos como una forma de usar el lenguaje Python en sí mismo como un marco en el que los objetos que creas se pueden integrar sin problemas.

Una segunda razón, respaldada por citas de Guido van Rossum como this , es que es más fácil de leer y escribir len (s) que s.len () .

La notación len (s) es consistente con operadores unarios con notación de prefijo, como abs (n) . len () se usa mucho más a menudo que abs () , y merece ser tan fácil de escribir.

También puede haber una razón histórica: en el lenguaje ABC que precedió a Python (y fue muy influyente en su diseño), había un operador unario escrito como #s que significaba len (s) .

met% python -c 'import this' | grep 'only one'
There should be one-- and preferably only one --obvious way to do it.

Aquí hay algunas respuestas geniales, así que antes de dar las mías, me gustaría resaltar algunas de las gemas (no he pensado en el juego de palabras con rubí) que he leído aquí.

  • Python no es un lenguaje OOP puro, es un lenguaje multipropósito de propósito general que permite al programador usar el paradigma con el que se sienten más cómodos y / o el paradigma más adecuado para su solución.
  • Python tiene funciones de primera clase, por lo que len es en realidad un objeto. Ruby, por otro lado, no tiene funciones de primera clase. Por lo tanto, el objeto de función len tiene sus propios métodos que puede inspeccionar ejecutando dir (len) .

Si no le gusta la forma en que funciona en su propio código, es trivial que vuelva a implementar los contenedores utilizando su método preferido (vea el ejemplo a continuación).

>>> class List(list):
...     def len(self):
...         return len(self)
...
>>> class Dict(dict):
...     def len(self):
...         return len(self)
...
>>> class Tuple(tuple):
...     def len(self):
...         return len(self)
...
>>> class Set(set):
...     def len(self):
...         return len(self)
...
>>> my_list = List([1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'])
>>> my_dict = Dict({'key': 'value', 'site': 'stackoverflow'})
>>> my_set = Set({1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'})
>>> my_tuple = Tuple((1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'))
>>> my_containers = Tuple((my_list, my_dict, my_set, my_tuple))
>>>
>>> for container in my_containers:
...     print container.len()
...
15
2
15
15

También puedes decir

>> x = 'test'
>> len(x)
4

Utilizando Python 2.7.3.

¿No?

>>> "abc".__len__()
3
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top