Apprentissage de la fonction magique Python __missing__

WBOY
Libérer: 2022-03-14 10:14:37
original
2398 Les gens l'ont consulté

Cet article vous apporte des connaissances pertinentes sur python, qui présente principalement des problèmes liés à la fonction "__missing__()". Jetons un coup d'œil ensemble à cette fonction magique. J'espère qu'elle sera utile à tout le monde.

Apprentissage de la fonction magique Python __missing__

Apprentissage recommandé : Tutoriel d'apprentissage Python

1. Le __missing__()

, quelque peu précieux, lors de l'obtention de la valeur à partir d'un dictionnaire ordinaire, la clé peut ne pas exister :

dd = {'name':'PythonCat'}
dd.get('age')        # 结果:None
dd.get('age', 18)    # 结果:18
dd['age']            # 报错 KeyError
dd.__getitem__('age')  # 等同于 dd['age']
Copier après la connexion

Apprentissage de la fonction magique Python __missing__

Pour l'obtention (), elle a une valeur de retour et le deuxième paramètre peut être transmis comme contenu de retour lorsque la clé n'existe pas, il est donc acceptable. Cependant, les deux autres méthodes d’écriture signaleront des erreurs.

Afin de résoudre le problème de ces deux dernières méthodes d'écriture, vous pouvez utiliser la méthode magique __missing__().

Maintenant, supposons que nous ayons une requête comme celle-ci : prenez la valeur correspondant à une clé dans le dictionnaire, renvoyez la valeur s'il y a une valeur, insérez la clé s'il n'y a pas de valeur et donnez-lui une valeur par défaut (telle que une liste vide).

Si vous utilisez un dict natif, ce n'est pas facile à implémenter. Cependant, Python fournit une classe d'extension très simple à utiliser collections.defaultdict : collections.defaultdict

Apprentissage de la fonction magique Python __missing__

如图所示,当取不存在的 key 时,没有再报 KeyError,而是默认存入到字典中。

为什么 defaultdict 可以做到这一点呢?

原因是 defaultdict 在继承了内置类型 dict 之后,还定义了一个 __missing__() 方法,当 __getitem__取不存在的值时,它就会调用入参中传入的工厂函数(上例是调用 list(),创建空列表)。

作为最典型的示例,defaultdict 在文档注释中写到:

Apprentissage de la fonction magique Python __missing__

简而言之,__missing__()的主要作用就是由__getitem__在缺失 key 时调用,从而避免出现 KeyError。

另外一个典型的使用例子是collections.Counter,它也是 dict 的子类,在取未被统计的 key 时,返回计数 0:

Apprentissage de la fonction magique Python __missing__

2、神出鬼没的__missing__()

由上可知,__missing__()在__getitem__()取不到值时会被调用,但是,我不经意间还发现了一个细节:__getitem__()在取不到值时,并不一定会调用__missing__()。

这是因为它并非内置类型的必要属性,并没有在字典基类中被预先定义。

如果你直接从 dict 类型中取该属性值,会报属性不存在:AttributeError: type object 'object' has no attribute '__missing__'

Apprentissage de la fonction magique Python __missing__

Comme le montre la figure, lorsque fet ching une clé inexistante temps, plus de rapport KeyError, mais stockez-le dans le dictionnaire par défaut.

Apprentissage de la fonction magique Python __missing__Pourquoi defaultdict peut-il faire cela ?

La raison est que defaultdict définit également une méthode __missing__() après avoir hérité du dict de type intégré. Lorsque __getitem__ prend une valeur qui n'existe pas, il appellera la fonction d'usine passée dans le paramètre d'entrée (l'exemple ci-dessus est Call). list(), créant une liste vide).

Comme exemple le plus typique, defaultdict écrit dans les commentaires de la documentation :

Apprentissage de la fonction magique Python __missing__

En bref, la fonction principale de Apprentissage de la fonction magique Python __missing____missing__() est d'être appelée par __getitem__ lorsque la clé est manquante, évitant ainsi KeyError.

Un autre exemple d'utilisation typique est collections.Counter, qui est également une sous-classe de dict. Lors de la prise d'une clé non comptée, un compte de 0 est renvoyé :

Apprentissage de la fonction magique Python __missing__

2.

Par Comme peut Comme le montre ce qui précède, __missing__() sera appelé lorsque __getitem__() ne peut pas obtenir la valeur. Cependant, j'ai accidentellement découvert un détail :

__getitem__() n'appelle pas nécessairement __missing__( lorsqu'il ne peut pas obtenir la valeur. ).

C'est parce qu'il ne s'agit pas d'un attribut nécessaire du type intégré et qu'il n'est pas prédéfini dans la classe de base du dictionnaire.

Apprentissage de la fonction magique Python __missing__Si vous prenez la valeur de l'attribut directement du type dict, il signalera que l'attribut n'existe pas : AttributeError : l'objet de type 'object' n'a pas d'attribut '__missing__'.

🎜Utilisez dir() pour vérifier et constater que l'attribut n'existe pas : 🎜🎜🎜🎜🎜Si vous vérifiez depuis la classe parent de dict, qui est un objet, vous trouverez également le même résultat. 🎜🎜Que se passe-t-il ? Pourquoi n'y a-t-il pas d'attribut __missing__ à la fois dans le dict et dans l'objet ? 🎜🎜Cependant, en vérifiant la dernière documentation officielle, l'objet contient clairement cet attribut : 🎜🎜🎜🎜🎜Source : https://docs.python.org/3/reference/datamodel.html?highlight=__missing__#object.__missing__🎜 🎜 Autrement dit, théoriquement __missing__ sera prédéfini dans la classe d'objet, et sa documentation le prouve, mais en fait ce n'est pas défini ! Il y a un décalage entre le document et la réalité ! 🎜🎜De cette façon, lorsqu'une sous-classe de dict (comme defaultdict et Counter) définit __missing__, cette méthode magique n'appartient en réalité qu'à cette sous-classe, c'est-à-dire : 🎜C'est une méthode magique née dans la sous-classe ! 🎜🎜🎜D'après cela, j'ai une supposition immature : __getitem__() déterminera si l'objet actuel est une sous-classe de dict et s'il a __missing__(), puis l'appellera (si la classe parent a également cette méthode, alors il ne portera pas de jugement d'abord, mais l'appellera directement). 🎜🎜J'ai évoqué cette conjecture dans le groupe de communication, et certains étudiants ont rapidement trouvé la vérification dans le code source de CPython : 🎜🎜🎜🎜

Et c'est intéressant, Les méthodes magiques qui n'existent que sur les sous-classes des types intégrés, En regardant l'ensemble du monde Python, il est probablement difficile de trouver un deuxième exemple.

J'ai soudainement eu une association : cet insaisissable __missing__() est comme un magicien doué pour "transformer une personne vivante". D'abord, laissez le public le voir à travers la vitre à l'extérieur (c'est-à-dire un document officiel), mais quand la porte est ouverte. ouvert, il n'est pas à l'intérieur (c'est-à-dire un type intégré), et lorsque les accessoires sont modifiés, il apparaît à nouveau intact (c'est-à-dire une sous-classe de dict).

3. La magie du __missing__()

__missing__() enchanté, en plus de la « magie » elle-même, elle nécessite également une « magie » puissante pour être conduite.

Dans le dernier article, j'ai découvert que les méthodes magiques natives sont indépendantes les unes des autres. Elles peuvent avoir la même logique de base dans l'interface du langage C, mais dans l'interface du langage Python, il n'y a pas de relation d'appel :

Apprentissage de la fonction magique Python __missing__

.

Magie Ce type de performance « sans contact » des méthodes viole le principe général de réutilisation du code et est également la raison pour laquelle les sous-classes des types intégrés ont des comportements étranges.

Python officiel préfère fournir de nouvelles sous-classes UserString, UserList et UserDict plutôt que de réutiliser les méthodes magiques. La seule explication raisonnable semble être que le coût de l'appel des méthodes magiques est trop élevé.

Cependant, pour le cas particulier __missing__(), Python doit faire des compromis et payer ce prix !

__missing__() est un "citoyen de seconde classe" de méthodes magiques. Il n'a pas d'entrée d'appel indépendante et ne peut être appelé passivement que par __getitem__(), c'est-à-dire que __missing__() dépend de __getitem__().

Différent de ces "Citoyens de première classe", tels que __init__(), __enter__(), __len__(), __eq__(), etc., ils sont soit déclenchés à un certain nœud du cycle de vie ou d'exécution de l'objet processus, soit déclenché par une fonction ou un opérateur intégré. Ce sont des événements relativement indépendants et n'ont aucune dépendance.

__missing__() dépend de __getitem__() pour réaliser l'appel de méthode ; et __getitem__() dépend également de __missing__() pour obtenir une fonctionnalité complète.

Pour y parvenir, __getitem__() ouvre une porte dérobée dans le code de l'interpréteur, revenant de l'interface du langage C vers l'interface Python pour appeler la méthode spécifique nommée "__missing__".

Apprentissage de la fonction magique Python __missing__

Et c'est là la vraie "magie". Jusqu'à présent, __missing__() semble être la seule méthode magique qui bénéficie d'un tel traitement !

4. Résumé

Le dictionnaire Python fournit deux méthodes intégrées pour obtenir des valeurs, à savoir __getitem__() et get() Lorsque la valeur n'existe pas, leurs stratégies de traitement sont différentes : La première signalera une erreur KeyError, qui renverra Aucun. <code>KeyError,而后者会返回 None。

为什么 Python 要提供两个不同的方法呢?或者应该问,为什么 Python 要令这两个方法做出不一样的处理呢?

这可能有一个很复杂(也可能是很简单)的解释,本文暂不深究了。

不过有一点是可以确定的:即原生 dict 类型简单粗暴地抛KeyError

Pourquoi Python propose-t-il deux méthodes différentes ? Ou vous devriez vous demander pourquoi Python gère ces deux méthodes différemment ?

Cela peut avoir une explication très compliquée (ou très simple), que je n’aborderai pas dans cet article. Mais une chose est sûre : le type dict natif renvoie simplement et grossièrement KeyError.

Afin de donner au type de dictionnaire des performances plus puissantes (ou de laisser __getitem__() se comporter comme get()), Python permet aux sous-classes du dictionnaire de définir __missing__() pour que __getitem__() recherche et appelle.

Cet article fait le tri des principes d'implémentation de __missing__(), révélant qu'il ne s'agit pas d'une existence discrète, bien au contraire, C'est le seul cas particulier qui brise les barrières entre les méthodes magiques et les supports appelés par d'autres méthodes magiques !

🎜Afin de maintenir l'indépendance des méthodes magiques, Python a pris grand soin d'introduire des classes dérivées telles que UserString, UserList et UserDict, mais pour __missing__(), il a choisi de faire des compromis. 🎜🎜Apprentissage recommandé : 🎜Tutoriel Python🎜🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:csdn.net
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal