Je sais que python a une len()
fonction qui est utilisée pour déterminer la taille d'une chaîne, mais je me demandais pourquoi ce n'était pas une méthode de l'objet chaîne.
Mettre à jour
Ok, j'ai réalisé que je me trompais d'une manière embarrassante. __len__()
est en fait une méthode d'un objet chaîne. Il semble juste étrange de voir du code orienté objet en Python en utilisant la fonction len sur les objets chaîne. En outre, il est également étrange de voir __len__
le nom au lieu de simplement len.
len(someObj)
ne remet passomeObj
de »__len__
fonction? tl; dr Oui, utilisez donc toujourslen()
au lieu de__len__()
.Réponses:
Les chaînes ont une méthode de longueur:
__len__()
Le protocole en Python consiste à implémenter cette méthode sur des objets qui ont une longueur et utilisent la
len()
fonction intégrée, qui l'appelle pour vous, de la même manière que vous implémenteriez__iter__()
et utiliseriez laiter()
fonction intégrée (ou que la méthode soit appelée derrière les scènes pour vous) sur des objets qui sont itérables.Voir Émulation des types de conteneurs pour plus d'informations.
Voici une bonne lecture sur le sujet des protocoles en Python: Python et le principe du moindre étonnement
la source
len
est idiote . Ils pensent qu'il est plus facile de forcer les gens à mettre en œuvre.__len__
que de forcer les gens à mettre en œuvre.len()
. C'est la même chose, et on a l'air beaucoup plus propre. Si la langue va avoir un POO__len__
, quel est le but de faire dans le mondelen(..)
__iter__
ou avec seulement__getitem__
etiter(x)
fonctionnera dans les deux cas. Vous pouvez créer un objet utilisable dans un contexte booléen avec__bool__
ou__len__
, etbool(x)
cela fonctionnera dans les deux cas. Etc. Je pense qu'Armin explique cela assez bien dans le post lié - mais même s'il ne l'a pas fait, appeler Python idiot à cause d'une explication extérieure par un gars qui est souvent publiquement en désaccord avec les développeurs principaux ne serait pas exactement juste ...zip
est une fonction de niveau supérieur, pas unezip_with
méthode. Etc. Le fait que tout soit un objet ne signifie pas qu'être un objet est la chose la plus importante de chaque chose.La réponse de Jim à cette question peut aider; Je le copie ici. Citant Guido van Rossum:
la source
Il y a un
len
méthode:la source
len
valide la sortie de__len__
. Voir Y alen(someObj)
someObj
__len__
- t-il un cas où n'appelle pas la fonction de? Les méthodes Dunder en général ne sont pas censées être appelées directement.Python est un langage de programmation pragmatique, et les raisons
len()
étant une fonction et non une méthode destr
,list
,dict
etc. sont pragmatiques.La
len()
fonction intégrée traite directement les types intégrés: l'implémentation CPython delen()
retourne en fait la valeur duob_size
champ dans laPyVarObject
structure C qui représente tout objet intégré de taille variable en mémoire. C'est beaucoup plus rapide que d'appeler une méthode - aucune recherche d'attribut ne doit se produire. Obtenir le nombre d'éléments dans une collection est une opération courante et doit travailler efficacement pour ces types de base et aussi divers questr
,list
,array.array
etc.Cependant, pour favoriser la cohérence, lors de l'application
len(o)
à un type défini par l'utilisateur, Python appelleo.__len__()
comme solution de secours.__len__
,__abs__
Et toutes les autres méthodes spéciales documentées dans le modèle de données Python , il est facile de créer des objets qui se comportent comme les Encastrements, permettant aux API expressives et très cohérentes que nous appelons « Pythonic ».En mettant en œuvre des méthodes spéciales, vos objets peuvent prendre en charge l'itération, surcharger les opérateurs d'infixe, gérer les contextes dans des
with
blocs, etc. Vous pouvez considérer le modèle de données comme un moyen d'utiliser le langage Python lui-même comme un 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 , est qu'il est plus facile à lire et à écrire
len(s)
ques.len()
.La notation
len(s)
est cohérente avec les opérateurs unaires avec la notation de préfixe, commeabs(n)
.len()
est utilisé beaucoup plus souventabs()
et mérite d'être aussi facile à écrire.Il peut également 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 comme
#s
ce qui signifiaitlen(s)
.la source
la source
Il y a d'excellentes réponses ici, et donc avant de donner la mienne, je voudrais souligner quelques-unes des gemmes (sans jeu de mots rubis) que j'ai lues ici.
len
comme un objet. Ruby, d'autre part, n'a pas de fonctions de première classe. Ainsi, l'len
objet fonction possède ses propres méthodes que vous pouvez inspecter en exécutantdir(len)
.Si vous n'aimez pas la façon dont cela fonctionne dans votre propre code, il est trivial pour vous de réimplémenter les conteneurs en utilisant votre méthode préférée (voir l'exemple ci-dessous).
la source
Quelque chose manque dans le reste des réponses ici: la
len
fonction vérifie que la__len__
méthode renvoie un résultat non négatifint
. Le fait qu'illen
s'agisse d'une fonction signifie que les classes ne peuvent pas remplacer ce comportement pour éviter la vérification. En tant que tel,len(obj)
donne un niveau de sécurité quiobj.len()
ne peut pas.Exemple:
Bien sûr, il est possible de "remplacer" la
len
fonction en la réaffectant en tant que variable globale, mais le code qui le fait est beaucoup plus suspect que le code qui remplace une méthode dans une classe.la source
sys.maxsize
, et qu'ilobj.__len__
existe en premier lieu. J'ai écrit une réponse à une autre question qui répertorie toutes les différentes vérifications.Vous pouvez également dire
Utilisation de Python 2.7.3.
la source
len
était déjà mentionnée dans les réponses précédentes. Quel est l'intérêt de cette "réponse", alors?Ce n'est pas le cas?
la source
len(someObj)
someObj
__len__
- t-il un cas où n'appelle pas la fonction de? Les méthodes Dunder en général ne sont pas censées être appelées directement.