Pourquoi python utilise-t-il deux underscores pour certaines choses?
je suis assez nouveau aux langages de programmation actuels, et Python est mon premier. Je connais un peu Linux, assez pour avoir un job d'été avec (je suis encore au lycée), et sur le tas, j'ai beaucoup de temps libre que j'utilise pour apprendre le Python.
il y a une chose qui me dérange. Qu'est-ce qui est exactement différent en Python quand vous avez des expressions comme
x.__add__(y) <==> x+y
x.__getattribute__('foo') <==> x.foo
je sais ce que font les méthodes et les trucs, et j'obtiens ce qu'ils font, mais ma question Est la suivante: en quoi ces méthodes de double underscore sont-elles différentes de leurs équivalents plus simples?
P., Je ne me dérange pas d'être sermonné sur l'histoire de la programmation, en fait, je trouve très utile de savoir :) si ce sont principalement des aspects historiques de Python, n'hésitez pas à commencer à radoter.
7 réponses
Eh bien, la puissance pour le programmeur est bonne, donc il devrait y avoir un moyen de personnaliser le comportement. Comme la surcharge de l'opérateur( __add__
, __div__
, __ge__
, ...), attribut access ( __getattribute__
, __getattr__
(ces deux sont différents), __delattr__
,...) etc. Dans de nombreux cas, comme les opérateurs, la syntaxe habituelle renvoie 1:1 à la méthode respective. Dans d'autres cas, il existe une procédure qui implique l'appel de la méthode choisie - par exemple, __getattr__
est appelé seulement si l'objet n'a pas l'attribut demandé et __getattribute__
n'est pas implémenté ou élevé AttributeError. Et certains d'entre eux sont vraiment des sujets avancés qui vous obtenez deeeeep dans les tripes du système d'objet et sont rarement nécessaires. Donc pas besoin de tous les apprendre, il suffit de consulter la référence lorsque vous avez besoin/voulez savoir. En parlant de référence, ici, c'est .
voici le créateur de Python l'expliquant :
... plutôt que de concevoir une nouvelle syntaxe pour types spéciaux de méthodes de classe (telles que comme les initialiseurs et destructeurs), je ces caractéristiques pourraient être manipulé en exigeant simplement l'utilisateur pour mettre en œuvre des méthodes spéciales des noms tels que
__init__
,__del__
, et ainsi de suite. Cette convention d'appellation était extrait de C où les identificateurs commencer avec des traits de soulignement sont réservés par le compilateur et ont souvent des spéciaux sens (par exemple, les macros telles que__FILE__
dans le préprocesseur C).
...
j'ai également utilisé cette technique pour permettre classes d'utilisateurs pour redéfinir le comportement des opérateurs de Python. Comme précédemment Python est implémenté en C et utilise des tables de pointeurs de fonction à mettre en œuvre diverses capacités de les objets intégrés (par exemple, "obtenir l'attribut", "ajouter" et "call"). De permettre la définition de ces capacités dans les classes définies par l'utilisateur, j'ai mappé différents pointeurs de fonction spéciales les noms de méthode tels que
__getattr__
,__add__
, et__call__
. Il y a un la correspondance directe entre ces les noms et les tables de la fonction pointeurs il faut définir quand implémenter de nouveaux objets Python en C.
lorsque vous démarrez une méthode avec deux underscores (et pas de underscore), les règles de Python sont appliquées. C'est une façon de simuler vaguement le mot-clé private
d'autres langages OO tels que C++ et Java. (Même ainsi, la méthode n'est pas encore techniquement privée de la façon dont les méthodes Java et C++ sont privées, mais il est "plus difficile d'obtenir" de l'extérieur de l'instance.)
méthodes à deux conducteurs et deux traînants les soulignements sont considérés comme des méthodes" intégrées", c'est-à-dire qu'ils sont utilisés par l'interpréteur et sont généralement des implémentations concrètes d'opérateurs surchargés ou d'autres fonctionnalités intégrées.
ils sont utilisés pour spécifier que L'interpréteur Python doit les utiliser dans des situations spécifiques.
par exemple, la fonction __add__
permet à l'opérateur +
de travailler pour des classes personnalisées. Sinon, vous obtiendrez une sorte d'erreur non définie en essayant d'ajouter.
d'un point de vue historique, les underscores principaux ont souvent été utilisés comme méthode pour indiquer au programmeur que les noms doivent être considérés comme internes au paquet/module/bibliothèque qui les définit. Dans les langues qui ne fournissent pas un bon support pour les espaces de noms privés, l'utilisation de underscores est une convention pour imiter cela. En Python, lorsque vous définissez une méthode appelée " _ _ foo__", le programmeur de maintenance sait par le nom qu'il se passe quelque chose de spécial qui n'est pas se produit avec une méthode appelée 'foo'. Si Python avait choisi d'Utiliser 'add' comme méthode interne pour surcharger'+', alors vous ne pourriez jamais avoir une classe avec une méthode' add ' sans causer beaucoup de confusion. Les underscores servent de signal pour dire qu'une certaine magie va se produire.
un certain nombre d'autres questions sont maintenant marquées comme des doublons de cette question, et au moins deux d'entre eux demandent ce que soit les méthodes __spam__
sont appelés, ou ce que la convention est appelée, et aucune des réponses existantes ne couvrent que, donc:
il n'y a en fait aucun nom officiel pour l'un ou l'autre.
de nombreux développeurs les appellent officieusement "méthodes dunder", pour"double UNDERscore".
certaines personnes utilisent le terme "magie méthodes", mais c'est quelque peu ambigu entre la signification de méthodes dunder, méthodes spéciales (Voir ci-dessous), ou quelque chose quelque part entre les deux.
Il y est un terme officiel "attributs spéciaux", qui recouvre près, mais pas complètement avec la dsous méthodes. Le modèle de données chapitre dans la référence n'explique jamais tout à fait ce qu'est un attribut spécial, mais l'idée de base est qu'il est au moins un
- un attribut fourni par l'interpréteur lui-même ou son code, comme
__name__
sur une fonction. - un attribut qui fait partie d'un protocole implémenté par l'interpréteur lui-même, comme
__add__
pour l'opérateur+
, ou__getitem__
pour l'indexation et le tranchage. - Un attribut que l'interprète est autorisé à rechercher spécialement, en ignorant l'instance et je vais droit à la classe, comme
__add__
encore.
la plupart des attributs spéciaux sont des méthodes, mais pas tous (par exemple, __name__
n'est pas). Et la plupart utilisent la convention "dunder", mais pas toutes (par exemple, la méthode next
sur les itérateurs en Python 2.x).
et pendant ce temps, la plupart des méthodes dunder sont des attributs spéciaux, mais pas tous-en particulier, il n'est pas si rare pour les bibliothèques stdlib ou externes de vouloir définir leurs propres protocoles qui travailler de la même façon, comme le pickle
protocole.
[spéculation] Python a été influencé par Algol68 , Guido peut-être utilisé Algol68 à la Université D'Amsterdam où Algol68 a un similaire" "150919920" régime de stropping appelé"citation stropping". Dans Algol68 les opérateurs , types et mots clés can apparaissent dans une police de caractères différente (habituellement * * en gras **, ou __souligné __), dans les fichiers de code source ce type de caractère est réalisé avec des guillemets, par exemple 'abs' (citant similaire à citer dans wikitexte ')
Algol68 ⇒ Python (Opérateurs mappés à des fonctions membres)
- 'et' ⇒ __et__ _ _
- " ou " ⇒ __ou__
- 'pas' ⇒ pas
- "entier" ⇒ _ _ trunc _ _
- ' shl ' ⇒ __ lshift _ _
- ' shr '⇒ _ _ rshift _ _
- 'remontée' ⇒ __sizeof__
- 'long' ⇒ _ _ long _ _ _
- ' int ' ⇒ _ _ int _ _
- 'réel' ⇒ __float__
- "format" ⇒ _ _ format _ _ _
- 'repr' ⇒ _ _ repr_ _
- ' abs ' ⇒ _ abs_ _ _
- "moins" ⇒ _ _ nég _ _
- 'moins' ⇒ __sous__
- "plus" ⇒ __add _ _
- "times" ⇒ __ mul _ _
- ' mod '⇒ _ mod_ _
- ' div '⇒ _ truediv _ _
- 'plus' ⇒ __div__
- 'jusqu'à' ⇒ __pow__
- ' im '⇒ imag
- 're' ⇒ réel
- 'conj' ⇒ conjugué
dans Algol68 ces termes ont été appelés en gras les noms de , par exemple abs , mais "sous-sous-abs" __abs__ en python.
mes 2 cents: ¢ ainsi parfois - comme un fantôme-quand vous coupez et collez des classes de python dans un wiki, vous vous réincarnerez magiquement algol68 bold mots clés. * 1519210920"