Pergunta

Eu sei que python tem uma função len() que é usado para determinar o tamanho de uma string, mas eu queria saber por que ele não é um método do objeto string.

Atualizar

Ok, eu percebi que estava vergonhosamente enganados. __len__() é realmente um método de um objeto string. Parece apenas estranho ver código orientado objeto em Python utilizando a função Len em objetos string. Além disso, também é estranho ver __len__ como o nome em vez de apenas len.

Foi útil?

Solução

Strings têm um método de comprimento: __len__()

O protocolo em Python é implementar este método sobre objectos que têm um comprimento e usam o built-in len() função noreferrer, que chama-lo para você, semelhante à maneira como você poderia implementar __iter__() e usar o built-in função iter() (ou ter o método chamado nos bastidores para você) em objetos que são iterable.

tipos de contêineres Veja Emulando para mais informações.

Aqui está uma boa leitura sobre o assunto de protocolos em Python: Python e o princípio da menor Astonishment

Outras dicas

A resposta de Jim para esta pergunta pode ajudar; Eu copiá-lo aqui. Citando Guido van Rossum:

Em primeiro lugar, eu escolhi len (x) sobre x.len () por razões de IHC (def __len __ () veio muito mais tarde). Há duas razões interligadas, na verdade, tanto HCI:

(a) Para algumas operações, prefixo notação apenas lê melhor do que postfix - (! E infix) prefixo operações têm uma longa tradição na matemática que gosta de anotações onde os visuais ajudam o pensamento matemático sobre um problema. Compare o fácil com que reescrever uma fórmula como x * (a + b) em x a + x b para a falta de jeito de fazer a mesma coisa usando uma notação OO matéria.

(b) Quando li o código que diz len (x) Eu sei que ele está pedindo para o comprimento de algo. Isto diz-me duas coisas: o resultado é um número inteiro, eo argumento é algum tipo de recipiente. Ao contrário, quando li x.len (), eu tenho que já sabe que x é algum tipo de recipiente implementação de uma interface ou herdar de uma classe que tem um len () padrão. Testemunha a confusão que ocasionalmente têm quando uma classe que não está a implementar um mapeamento tem um método get () ou as teclas (), ou algo que não é um arquivo tem um método write ().

dizendo a mesma coisa de outra maneira, eu vejo ‘len’ como uma operação integrada. Eu odeio perder isso. / ... /

Existe um método len:

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

Python é uma linguagem de programação pragmática, e as razões para len() sendo uma função e não um método de str, list, dict etc. são pragmáticos.

O len() built-in ofertas de função diretamente com tipos built-in: a implementação CPython de len() realmente retorna o valor do campo ob_size na PyVarObject C struct que representa qualquer um de tamanho variável embutido objecto na memória. Esta é muito mais rápido do que chamar um método - não precisa de atributo de pesquisa para acontecer. Obtendo o número de itens em uma coleção é uma operação comum e deve trabalhar de forma eficiente para tais tipos básicos e diversos como str, list, array.array etc.

No entanto, para promover a coerência, ao aplicar len(o) a um tipo definido pelo usuário, o Python chama o.__len__() como um fallback. __len__, __abs__ e todos os outros métodos especiais documentados no Python Data Model tornar mais fácil para criar objetos que se comportam como os embutidos, possibilitando que as APIs expressivos e altamente consistentes chamamos de "Pythonic".

Ao implementar métodos especiais seus objetos podem apoiar iteração, operadores de sobrecarga infixas, gerenciar contextos em with blocos etc. Você pode pensar o modelo de dados como uma maneira de usar-se a linguagem Python como um quadro onde os objetos criados podem ser integrados sem problemas.

A segunda razão, apoiado por citações de Guido van Rossum como esta , é que é mais fácil de ler e len(s) gravação de s.len().

O len(s) notação é consistente com operadores unários com notação de prefixo, como abs(n). len() é usado muito mais frequentemente do que abs(), e merece ser tão fácil de escrever.

Há também pode ser uma razão histórica:. Na língua ABC que precedeu Python (e foi muito influente na sua concepção), houve um operador unário escrito como #s que significava len(s)

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

Há algumas grandes respostas aqui, e assim antes de eu dar o meu próprio eu gostaria de destacar algumas das gemas (sem trocadilho rubi intencional) Eu li aqui.

  • Python não é uma linguagem OOP pura -. É um propósito geral, a linguagem multi-paradigma que permite que o programador para usar o paradigma que está mais confortável com e / ou o paradigma de que é mais adequado para a sua solução
  • Python tem funções de primeira classe, de modo len é realmente um objeto. Ruby, por outro lado, não tem funções de primeira classe. Assim, o objeto de função len tem seu próprio métodos que você pode inspecionar executando dir(len).

Se você não gosta da maneira como isso funciona em seu próprio código, é trivial para você reimplementar os recipientes usando seu método preferido (veja exemplo abaixo).

>>> 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

Você também pode dizer

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

Usando Python 2.7.3.

Ele não?

>>> "abc".__len__()
3
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top