Question

Je sais que python a une fonction len () qui permet de déterminer la taille d'une chaîne, mais je me demandais pourquoi ce n'est pas une méthode de l'objet chaîne.

Mettre à jour

D'accord, j'ai compris que je me suis trompé de manière embarrassante. __ len __ () est en réalité une méthode d'un objet chaîne. Il semble étrange de voir du code orienté objet en Python utilisant la fonction len sur des objets chaîne. En outre, il est également étrange de voir __ len __ comme nom plutôt que juste len.

Était-ce utile?

La solution

Les chaînes ont une méthode de longueur: __ len __ ()

Le protocole en Python consiste à implémenter cette méthode sur les objets ayant une longueur et à utiliser le len () , qui l'appelle pour vous, de la même manière que vous mettriez en œuvre __ iter __ () et utilisez la fonction iter () intégrée (ou faites appeler la méthode en arrière-plan pour vous) sur des objets qui sont itérables.

Voir Emulation des types de conteneur pour plus d'informations.

Voici une bonne lecture sur les protocoles en Python: Python et le principe de moindre étonnement

Autres conseils

La réponse de Jim à cette question peut aider; Je le copie ici. Citant Guido van Rossum:

  

Tout d’abord, j’ai choisi len (x) plutôt que x.len () pour des raisons liées à HCI (def __len __ () est venu beaucoup plus tard). Il existe en fait deux raisons étroitement liées, à la fois HCI:

     

(a) Pour certaines opérations, la notation de préfixe se lit mieux que postfix & # 8212; les opérations préfixes (et infixes!) ont une longue tradition en mathématiques qui aime les notations où les éléments visuels aident le mathématicien à réfléchir à un problème. Comparez la facilité avec laquelle nous réécrivons une formule telle que x * (a + b) dans x a + x b à la maladresse de faire la même chose en utilisant une notation OO brute.

     

(b) Quand je lis le code qui dit len ??(x), je sais qu’il demande la longueur d’un objet. Cela me dit deux choses: le résultat est un entier et l'argument est une sorte de conteneur. Au contraire, quand je lis x.len (), je dois déjà savoir que x est une sorte de conteneur implémentant une interface ou héritant d'une classe ayant un len () standard. Observez la confusion qui règne parfois quand une classe qui n’implémente pas de mappage utilise une méthode get () ou keys (), ou quelque chose qui n’est pas un fichier a une méthode write ().

     

En disant la même chose d'une autre manière, je vois & ls & ls & 8213; comme une opération intégrée. Je ne voudrais pas perdre ça. / & # 8230; /

Il existe une méthode len :

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

Python est un langage de programmation pragmatique, et les raisons pour lesquelles len () sont une fonction et non une méthode de str , liste , dict etc. sont pragmatiques.

La fonction intégrée len () traite directement les types intégrés: l'implémentation CPython de len () renvoie en réalité la valeur de ob_size Champ dans le PyVarObject C struct qui représente tout objet intégré de taille variable en mémoire. C'est beaucoup beaucoup plus rapide que d'appeler une méthode: aucune recherche d'attribut n'est nécessaire. Obtenir le nombre d'éléments dans une collection est une opération courante et doit fonctionner efficacement pour des types de base aussi variés que str , liste , array.array etc.

Cependant, pour favoriser la cohérence, lorsque vous appliquez len (o) à un type défini par l'utilisateur, Python appelle o .__ len __ () comme solution de secours. __ len __ , __ abs __ et toutes les autres méthodes spéciales décrites dans la Le modèle de données Python facilite la création d’objets se comportant comme les éléments intégrés, permettant ainsi les API expressives et très cohérentes que nous appelons "Pythonic".

En appliquant des méthodes spéciales, vos objets peuvent prendre en charge l'itération, surcharger les opérateurs d'infix, gérer les contextes dans des avec des blocs , etc. Vous pouvez penser au modèle de données comme un moyen d'utiliser le langage Python lui-même en tant que cadre où les objets que vous créez peuvent être intégrés de manière transparente.

Une deuxième raison, appuyée par des citations de Guido van Rossum comme celle-ci , c’est qu’il est plus facile de lire et d’écrire len (s) que s.len () .

La notation len (s) est cohérente avec les opérateurs unaires à notation préfixée, comme abs (n) . len () est utilisé beaucoup plus souvent que abs () , et il mérite d'être aussi facile à écrire.

Il peut aussi y avoir une raison historique: dans le langage ABC qui a précédé Python (et était très influent dans sa conception), il y avait un opérateur unaire écrit avec #s , ce qui signifiait len (s) .

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

Il y a d'excellentes réponses ici, et donc avant de vous donner la mienne, j'aimerais souligner quelques-unes des pierres précieuses que j'ai lues ici (sans jeu de mots rubis).

  • Python n’est pas un pur langage POO - c’est un langage multi-paradigme à usage général qui permet au programmeur d’utiliser le paradigme avec lequel il est le plus à l’aise et / ou celui qui convient le mieux à sa solution.
  • Python a des fonctions de première classe, donc len est en réalité un objet. Ruby, d'autre part, n'a pas de fonctions de première classe. Donc, l'objet de fonction len a ses propres méthodes que vous pouvez inspecter en exécutant dir (len) .

Si vous n'aimez pas la façon dont cela fonctionne dans votre propre code, il est facile pour vous de réimplémenter les conteneurs en utilisant votre méthode préférée (voir l'exemple ci-dessous).

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

Vous pouvez aussi dire

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

Utilisation de Python 2.7.3.

Ça ne marche pas?

>>> "abc".__len__()
3
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top