Table des matières
Qu'est-ce qu'une « méthode générique » ?
Par exemple
一般实现
有没有更好的方式?
缺点
#1 单分派
#2 不支持 typing
替代方案:multimethod 库
优势
更更好的实践方式
究极好的实践方式(真正的方法重载)
#1 Envoi unique
#2 ne prend pas en charge la saisie
Maison développement back-end Tutoriel Python Comment définir la surcharge de plusieurs méthodes de constructeur et les méthodes génériques dans les classes Python

Comment définir la surcharge de plusieurs méthodes de constructeur et les méthodes génériques dans les classes Python

May 09, 2023 pm 02:34 PM
python

    Qu'est-ce qu'une « méthode générique » ?

    Une méthode composée de plusieurs méthodes qui implémentent la même opération pour différents types.

    Par exemple

    Il existe désormais une exigence qui vous oblige à créer une classe de date personnalisée (CustomDate) de la manière suivante : CustomDate):

    • 时间戳

    • 年、月、日(包含三个整数的元组)

    • ISO 格式的字符串

    • Datetime

    一般实现

    from datetime import date, datetime
    class CustomDate:
        def __init__(self, arg):
            if isinstance(arg, (int, float)):
                self.__date = date.fromtimestamp(arg)
            elif isinstance(arg, tuple) and len(arg) == 3 and all(map(lambda x: isinstance(x, int), arg):
                self.__date = date(*arg)
            elif isinstance(arg, str):
                self.__date = date.fromisoformat(arg)
            elif isinstance(arg, datetime):
                self.__date = datetime.date()
            else:
                raise TypeError("could not create instance from " + type(arg).__name__)
        @property
        def date():
            return self.__date
    Copier après la connexion

    注:这里暂不讨论传入的日期/时间戳合不合法,仅仅只对类型做大致判断。

    有没有更好的方式?

    我们可以将不同的构建方式拆分为多个方法,并利用 functools 中的 singledispatchmethod 装饰器来根据传入的参数类型决定调用哪个方法。

    from datetime import date, datetime
    from functools import singledispatchmethod
    class CustomDate:
        @singledispatchmethod
        def __init__(self, arg):
            raise TypeError("could not create instance from " + type(arg).__name__)
        @__init__.register(int)
        @__init__.register(float)
        def __from_timestamp(self, arg):
            self.__date = date.fromtimestamp(arg)
        @__init__.register(tuple)
        def __from_tuple(self, arg):
            if len(arg) == 3 and all(map(lambda x: isinstance(x, int), arg)):
                self.__date = date(*arg)
            else:
                raise ValueError("could not create instance from a malformed tuple")
        @__init__.register(str)
        def __from_isoformat(self, arg):
            self.__date = date.fromisoformat(arg)
        @__init__.register(datetime)
        def __from_datetime(self, arg):
            self.__date = arg.date()
        @property
        def date(self):
            return self.__date
    Copier après la connexion

    这样一来,我们便能将每种参数类型的初始化独立成一个个的方法了。

    缺点

    #1 单分派

    在调用期间应该使用哪个方法实现由分派算法决定。如果该算法只基于单个参数的类型来决定使用哪个方法实现,则称其为单分派。

    singledispatchmethod 就是就是单分派的。也就是说,只有第一个参数会作为考量。这在实际业务中是远远不足的。

    #2 不支持 typing

    然而,如上,对元组中元素类型判断还是需要我们用 if/else 实现。也就是说,我们不能使用 typing.Tuple[int, int, int]

    作为一种折中的方案,或许我们可以定义一个 ThreeIntTuple 类来对其进行限定,将这些判断从 CustomDate 类中隔离开来。

    这里仅提供一个思路让大家参考,我就不实现了(因为我们有更好的方式 xD)。

    替代方案:multimethod 库

    这个库不是标准库之一,需要通过 pip 安装:

    pip install multimethod
    Copier après la connexion

    优势

    multimethod 采用的是多分派算法,能更好地满足更复杂的场景。此外,该库对 typing 中的类型也有不错的支持。

    更更好的实践方式

    回到上面的问题,我们可以这么改进:

    • 使用 multimethod 方法来替代 singledispatchmethod

    • 使用 Tuple[int, int, int] 来替代 tuple,不再需要手动校验元组的长度和元素类型了;

    from datetime import date, datetime
    from typing import Tuple, Union
    from multimethod import multimethod
    class CustomDate:
        @multimethod
        def __init__(self, arg):
            raise TypeError("could not create instance from " + type(arg).__name__)
        @__init__.register
        def __from_timestamp(self, arg: Union[int, float]):
            self.__date = date.fromtimestamp(arg)
        @__init__.register
        def __from_tuple(self, arg: Tuple[int, int, int]):
            self.__date = date(*arg)
        @__init__.register
        def __from_isoformat(self, arg: str):
            self.__date = date.fromisoformat(arg)
        @__init__.register
        def __from_datetime(self, arg: datetime):
            self.__date = arg.date()
        @property
        def date(self):
            return self.__date
    Copier après la connexion

    究极好的实践方式(真正的方法重载)

    在此之前,先问大家一个简单的问题(这跟我们之后的内容有很大的联系):

    class A:
        def a(self):
            print(1)
        def a(self):
            print(2)
    A().a()
    Copier après la connexion

    以上这段代码会输出什么?还是会抛出错误?

    输出 2

    在 Python 中,如果定义了重名的方法,最后一个方法是会覆盖掉之前的方法的。

    但你或许不知,我们可以通过元类(metaclass)来改变这一行为:

    class MetaA(type):
        class __prepare__(dict):
            def __init__(*args):
                pass
            def __setitem__(self, key, value):
                if self.get('a'):  # Line 7
                    super().__setitem__('b', value)  # Line 8
                else:	
                    super().__setitem__(key, value)
    class A(metaclass=MetaA):
        def a(self):
            print(1)
        def a(self):
            print(2)
    A().a()  # => 1
    A().b()  # => 2  # Line 22
    Copier après la connexion

    在第 7 和第 8 行,我们将重名的 a 方法改名为 b,并在第 22 行成功地调用它了。

    multimethod 的维护者们很好地运用了这一点,对重名的方法进行了处理,以达到一种“特殊的效果”。

    回到正题,我们可以做出如下改进:

    • multimethod.multidata 设置为 CustomDate 类的元类;

    • 将所有方法命名为 __init__

        < li>

        Horodatage
    • Année, mois, jour (tuple contenant trois entiers)

      🎜
    • 🎜Chaîne au format ISO🎜🎜
    • 🎜Datetime</code > Implémentation générale de la classe 🎜 🎜🎜🎜🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>from datetime import date, datetime from typing import Tuple, Union from multimethod import multimeta class CustomDate(metaclass=multimeta): def __init__(self, arg: Union[int, float]): self.__date = date.fromtimestamp(arg) def __init__(self, arg: Tuple[int, int, int]): self.__date = date(*arg) def __init__(self, arg: str): self.__date = date.fromisoformat(arg) def __init__(self, arg: datetime): self.__date = arg.date() def __init__(self, arg): raise TypeError(&quot;could not create instance from &quot; + type(arg).__name__) @property def date(self): return self.__date</pre><div class="contentsignin">Copier après la connexion</div></div>🎜 Remarque : Nous ne discuterons pas de la question de savoir si l'horodatage entrant est légal ou non, mais nous porterons seulement un jugement approximatif sur le type. 🎜🎜Y a-t-il une meilleure façon ? 🎜🎜Nous pouvons diviser différentes méthodes de construction en plusieurs méthodes et utiliser le décorateur <code>singledispatchmethod dans functools pour décider quelle méthode appeler en fonction du type de paramètres transmis. 🎜rrreee🎜De cette façon, nous pouvons séparer l'initialisation de chaque type de paramètre en méthodes distinctes. 🎜🎜Inconvénients🎜
      #1 Envoi unique
      🎜L'implémentation de la méthode à utiliser lors de l'appel est déterminée par l'algorithme de répartition. Si l’algorithme décide quelle implémentation de méthode utiliser en fonction uniquement du type d’un seul paramètre, on parle de répartition unique. 🎜🎜singledispatchmethod est une expédition unique. Autrement dit, seul le premier paramètre sera pris en compte. C’est loin d’être suffisant dans la réalité des affaires. 🎜
      #2 ne prend pas en charge la saisie
      🎜Cependant, comme mentionné ci-dessus, nous devons toujours utiliser if/else pour déterminer le type d'éléments dans un tuple. Autrement dit, nous ne pouvons pas utiliser typing.Tuple[int, int, int]. 🎜🎜À titre de compromis, nous pouvons peut-être définir une classe ThreeIntTuple pour la limiter et isoler ces jugements de la classe CustomDate. 🎜🎜Voici juste une idée pour votre référence, je ne la mettrai pas en œuvre (car nous avons une meilleure façon xD). 🎜🎜Alternative : bibliothèque multiméthode🎜🎜Cette bibliothèque ne fait pas partie des bibliothèques standards et doit être installée via pip : 🎜rrreee🎜Avantages🎜🎜multiméthode utilise un algorithme multi-dispatch, qui peut mieux répondre scène d’exigences plus complexes. De plus, la bibliothèque prend bien en charge les types en typing. 🎜🎜Meilleure pratique🎜🎜Retour à la question ci-dessus, nous pouvons l'améliorer comme ceci :🎜
      • 🎜Utilisez plutôt la méthode multimethod singledispatchmethod ; 🎜🎜
      • 🎜Utilisez Tuple[int, int, int] pour remplacer tuple, vous n'avez plus besoin de vérifier manuellement les tuples. La longueur et type d'élément de ) : 🎜rrreee🎜Que produira le code ci-dessus ? Ou est-ce que cela générera une erreur ? 🎜🎜Sortie 2. 🎜🎜En Python, si des méthodes portant le même nom sont définies, la dernière méthode écrasera la méthode précédente. 🎜🎜Mais vous ne savez peut-être pas que nous pouvons changer ce comportement via la métaclasse : 🎜rrreee🎜Dans les lignes 7 et 8, nous renommeons la méthode a du même nom en b et l'appelle avec succès sur la ligne 22. 🎜🎜Les responsables de multimethod en ont fait bon usage et ont traité des méthodes avec des noms en double pour obtenir un "effet spécial". 🎜🎜Revenant au sujet, nous pouvons apporter les améliorations suivantes : 🎜
        • 🎜Définissez multimethod.multidata sur CustomDate Métaclasse de la classe ; 🎜🎜
        • 🎜Nommez toutes les méthodes __init__. 🎜🎜🎜rrreee🎜En termes d'effet, c'est exactement la même chose que la surcharge de méthodes de langage statique ! 🎜

      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!

    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

    Outils d'IA chauds

    Undresser.AI Undress

    Undresser.AI Undress

    Application basée sur l'IA pour créer des photos de nu réalistes

    AI Clothes Remover

    AI Clothes Remover

    Outil d'IA en ligne pour supprimer les vêtements des photos.

    Undress AI Tool

    Undress AI Tool

    Images de déshabillage gratuites

    Clothoff.io

    Clothoff.io

    Dissolvant de vêtements AI

    Video Face Swap

    Video Face Swap

    Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

    Article chaud

    <🎜>: Bubble Gum Simulator Infinity - Comment obtenir et utiliser les clés royales
    4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
    <🎜>: Grow A Garden - Guide de mutation complet
    3 Il y a quelques semaines By DDD
    Nordhold: Système de fusion, expliqué
    4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
    Mandragora: Whispers of the Witch Tree - Comment déverrouiller le grappin
    3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

    Outils chauds

    Bloc-notes++7.3.1

    Bloc-notes++7.3.1

    Éditeur de code facile à utiliser et gratuit

    SublimeText3 version chinoise

    SublimeText3 version chinoise

    Version chinoise, très simple à utiliser

    Envoyer Studio 13.0.1

    Envoyer Studio 13.0.1

    Puissant environnement de développement intégré PHP

    Dreamweaver CS6

    Dreamweaver CS6

    Outils de développement Web visuel

    SublimeText3 version Mac

    SublimeText3 version Mac

    Logiciel d'édition de code au niveau de Dieu (SublimeText3)

    Sujets chauds

    Tutoriel Java
    1672
    14
    Tutoriel PHP
    1276
    29
    Tutoriel C#
    1256
    24
    PHP et Python: différents paradigmes expliqués PHP et Python: différents paradigmes expliqués Apr 18, 2025 am 12:26 AM

    PHP est principalement la programmation procédurale, mais prend également en charge la programmation orientée objet (POO); Python prend en charge une variété de paradigmes, y compris la POO, la programmation fonctionnelle et procédurale. PHP convient au développement Web, et Python convient à une variété d'applications telles que l'analyse des données et l'apprentissage automatique.

    Choisir entre PHP et Python: un guide Choisir entre PHP et Python: un guide Apr 18, 2025 am 12:24 AM

    PHP convient au développement Web et au prototypage rapide, et Python convient à la science des données et à l'apprentissage automatique. 1.Php est utilisé pour le développement Web dynamique, avec une syntaxe simple et adapté pour un développement rapide. 2. Python a une syntaxe concise, convient à plusieurs champs et a un écosystème de bibliothèque solide.

    Comment exécuter le code sublime python Comment exécuter le code sublime python Apr 16, 2025 am 08:48 AM

    Pour exécuter le code Python dans le texte sublime, vous devez d'abord installer le plug-in Python, puis créer un fichier .py et écrire le code, et enfin appuyez sur Ctrl B pour exécuter le code, et la sortie sera affichée dans la console.

    PHP et Python: une plongée profonde dans leur histoire PHP et Python: une plongée profonde dans leur histoire Apr 18, 2025 am 12:25 AM

    PHP est originaire en 1994 et a été développé par Rasmuslerdorf. Il a été utilisé à l'origine pour suivre les visiteurs du site Web et a progressivement évolué en un langage de script côté serveur et a été largement utilisé dans le développement Web. Python a été développé par Guidovan Rossum à la fin des années 1980 et a été publié pour la première fois en 1991. Il met l'accent sur la lisibilité et la simplicité du code, et convient à l'informatique scientifique, à l'analyse des données et à d'autres domaines.

    Python vs JavaScript: la courbe d'apprentissage et la facilité d'utilisation Python vs JavaScript: la courbe d'apprentissage et la facilité d'utilisation Apr 16, 2025 am 12:12 AM

    Python convient plus aux débutants, avec une courbe d'apprentissage en douceur et une syntaxe concise; JavaScript convient au développement frontal, avec une courbe d'apprentissage abrupte et une syntaxe flexible. 1. La syntaxe Python est intuitive et adaptée à la science des données et au développement back-end. 2. JavaScript est flexible et largement utilisé dans la programmation frontale et côté serveur.

    Golang vs Python: performance et évolutivité Golang vs Python: performance et évolutivité Apr 19, 2025 am 12:18 AM

    Golang est meilleur que Python en termes de performances et d'évolutivité. 1) Les caractéristiques de type compilation de Golang et le modèle de concurrence efficace le font bien fonctionner dans des scénarios de concurrence élevés. 2) Python, en tant que langue interprétée, s'exécute lentement, mais peut optimiser les performances via des outils tels que Cython.

    Où écrire du code dans vscode Où écrire du code dans vscode Apr 15, 2025 pm 09:54 PM

    L'écriture de code dans Visual Studio Code (VSCODE) est simple et facile à utiliser. Installez simplement VScode, créez un projet, sélectionnez une langue, créez un fichier, écrivez du code, enregistrez-le et exécutez-le. Les avantages de VSCOD incluent la plate-forme multiplateuse, gratuite et open source, des fonctionnalités puissantes, des extensions riches et des poids légers et rapides.

    Comment exécuter Python avec le bloc-notes Comment exécuter Python avec le bloc-notes Apr 16, 2025 pm 07:33 PM

    L'exécution du code Python dans le bloc-notes nécessite l'installation du plug-in exécutable Python et du plug-in NPEXEC. Après avoir installé Python et ajouté un chemin à lui, configurez la commande "python" et le paramètre "{current_directory} {file_name}" dans le plug-in nppexec pour exécuter le code python via la touche de raccourci "F6" dans le bloc-notes.

    See all articles