Que faire lorsque l'imitation est intégrée à Python

introduction

Ce que je fais en imitant l'intégration en python, ou plutôt la délégation plutôt que l'héritage.

L'histoire que l'héritage est difficile

L'une des raisons pour lesquelles l'héritage est douloureux est que vous ne savez pas quelle méthode a été appelée.

Par exemple, pour C avec la relation d'héritage suivante

class A:
    def f(self):
        return "f"

    def g(self):
        return "g"


class B:
    def h(self):
        return "h"

    def i(self):
        return "i"


class C(A, B):
    def m(self):
        return (self.f(), self.i())

Il est difficile de comprendre le comportement de traitement de C # m (). Bien sûr, je pense que je suis généralement un peu plus précis sur le nom, donc je ne pense pas qu'il devrait être si mauvais.

En revanche, s'il est délégué, c'est encore mieux.

class C:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def m(self):
        return (self.a.f(), self.b.i())

En effet, il sera spécifié quelle méthode de la variable d'instance qui est conservée en interne est appelée.

intégrer go

Voici l'intégration de go. Cela peut également être considéré comme une fonctionnalité qui effectue la délégation de manière semi-automatique.

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

type ReadWriter interface {
    Reader
    Writer
}

ReadeWriter a des fonctions de lecture et d'écriture. En substance, il délègue simplement à la valeur qu'il a à l'intérieur. L'exemple ci-dessus était un exemple d'interface, mais il en va de même pour struct.

type ReadWriter struct {
    *Reader  // *bufio.Reader
    *Writer  // *bufio.Writer
}

Si vous faites quelque chose comme rw.Read () pour une variable rw qui devient var rw * ReadWriter ici, alors quelque chose comme` rw.Reader.Read () ʻest appelé.

Imitation de l'incorporation en python

Revenez à python. Vous avez mentionné dans le premier exemple que la délégation vaut mieux que l'héritage. Cependant, il n’a pas été complètement résolu par délégation. Vous pouvez appeler les méthodes A et B directement à partir de C. De plus, si vous faites quelque chose comme c.a.f () directement là où vous utilisez C, les valeurs qui peuvent réellement être utilisées seront fixées à l'instance C.

C'est pourquoi il arrive que vous vouliez que c.a.f () soit appelé en interne en appelant c.f (). Cela dit, il est difficile d'écrire explicitement les appels de méthode requis à chaque fois. Je serais heureux si vous pouviez le faire automatiquement. En d'autres termes, c'est une imitation de l'intégration de go.

Le sujet principal est d'ici, mais si vous voulez imiter l'intégration de go with python, je fais personnellement ce qui suit.

class C:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def m(self):
        return (self.a.f(), self.b.i())

    def __getattr__(self, name):
        return getattr(self.a, name)

Désormais, «c.f» deviendra automatiquement «c.a.f». Cela n'imite pas complètement l'intégration de go. Si un attribut qui n'existe pas est spécifié, il sera entièrement délégué à self.a. Vous pouvez le faire un peu plus explicitement ou de manière plus restrictive en utilisant la méta-programmation etc. Je pense que c'est suffisant pour le moment.

Lorsqu'il existe plusieurs sources d'héritage

Dans l'exemple d'origine, il y avait plusieurs sources d'héritage. Dans l'exemple précédent, nous ne pouvons gérer que le cas où il n'y a qu'une seule source d'héritage. Examinons également plusieurs cas. Le point à noter est comment utiliser getattr. Vous pouvez spécifier la valeur par défaut pour le troisième argument de getattr. Essayez de renvoyer une valeur spéciale au lieu de None. En effet, même si Aucun est défini, il recherchera la prochaine destination de recherche (au contraire, si vous souhaitez rechercher un autre candidat s'il n'y en a aucun, vous pouvez le faire. Comprenez le comportement. Je ne le recommande pas car ce sera difficile à faire).

missing = object()


class C:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def m(self):
        return (self.a.f(), self.b.i())

    def __getattr__(self, name):
        v = getattr(self.a, name, missing)
        if v is not missing:
            return v
        return getattr(self.b, name)

Maintenant c.i () appellera c.b.i () ʻet c.f () appellera c.a.f ()`.

au fait

En passant, dans l'exemple d'origine, j'ai écrit un exemple dans lequel une valeur qui hérite de plusieurs A et B est prise en charge par plusieurs destinations de transfert dans l'exemple final. Dans le code réel, il n'est pas recommandé d'effectuer un tel transfert implicite vers plusieurs destinations de transfert. En effet, il devient difficile de saisir le comportement en regardant le putt. Par conséquent, il est préférable de limiter autant que possible la destination du transfert à une seule.

Recommended Posts

Que faire lorsque l'imitation est intégrée à Python
[Question] Que se passe-t-il si vous utilisez% en python?
Ce que j'ai appris en Python
Je veux faire quelque chose avec Python à la fin
Que faire lorsque "SSL: CERTIFICATE_VERIFY_FAILED _ssl.c: 1056" apparaît en Python
Que faire lorsque ModuleNotFoundError: Aucun module nommé'XXX 'ne se produit en Python
Que faire lorsque le type de valeur est ambigu en Python?
Après tout, que dois-je utiliser pour faire des comparaisons de types en Python?
Je veux faire le test de Dunnett en Python
[Python] Ce que j'ai fait pour faire un test unitaire
Quand j'essaye matplotlib en Python, il dit 'cairo.Context'
Ce que j'ai fait lors de la mise à jour de Python 2.6 vers 2.7
Que dois-je faire avec DICOM de MPEG2?
Que faire pour obtenir une feuille de calcul Google en Python
[python] Que faire si vous obtenez une erreur avec send_keys dans le chrome sans tête
Que faire lorsqu'un avertissement apparaît autour de l'intégration de Python dans CheckHealth de Neovim
Ce que j'ai fait quand je suis resté coincé dans le délai avec lambda python
Que faire lorsque [Errno 2] Aucun fichier ou répertoire de ce type n'apparaît en Python
[Go 1.13] Que faire lorsque la disposition de répertoire inattendue: apparaît
[openpyxl] Que faire lorsque IllegalCharacterError apparaît dans pandas.DataFrame.to_excel
Que faire lorsque "impossible d'importer le nom xxx" [Python]
Ce à quoi j'étais accro lors de l'utilisation de Python tornado
Que faire si vous obtenez une erreur lors de l'importation de matplotlib en Python (Mac)
J'ai écrit python en japonais
Attention lorsque os.mkdir en Python
Je comprends Python en japonais!
Que faire lorsque ʻarguments [0] .scrollIntoView (); `échoue dans python sélénium
Ce que je suis resté coincé autour de l'interface graphique dans l'environnement python WSL
Je veux faire quelque chose comme sort uniq en Python
Ce à quoi j'étais accro lorsque l'utilisateur de traitement est passé à Python
Que faire lorsque "En-tête HTTP_HOST non valide" apparaît dans Django
Qu'est-ce qui a été demandé lors de l'utilisation de Random Forest dans la pratique
Que faire s'il n'y a pas de réponse en raison des paramètres de proxy dans le scraping Web Python
Que faire quand Ubuntu plante
[Python] Comment faire PCA avec Python
Précautions lors de l'utilisation de Pit avec Python
Que faire si vous obtenez moins zéro en Python
Comportement lors de la liste dans Python heapq
J'ai eu un AttributeError en me moquant de la méthode ouverte en python
Ce à quoi j'étais accro en présentant ALE à Vim pour Python
Ce à quoi j'étais accro avec json.dumps dans l'encodage base64 de Python
J'ai écrit Fizz Buzz en Python
Que faire avec la sortie de PYTHON?
Que faire si un avertissement de plate-forme non sécurisée apparaît lors de l'exécution de Python
J'ai essayé Grumpy (allez exécuter Python).
Je voulais faire quelque chose comme la pipe d'Elixir en Python
J'ai essayé d'étudier le processus avec Python
Scikit-learn ne peut pas être installé en Python
Scribble ce que j'ai utilisé lors de l'utilisation d'ipython dans le formatage des données de position
J'obtiens un attribut impossible à définir lors de l'utilisation de @property en python
J'ai écrit la file d'attente en Python
Ce que j'ai fait quand je voulais rendre Python plus rapide -Édition Numba-
Que faire lorsque vous obtenez "Je ne peux pas voir le site !!!!"
Que faire quand UnicodeDecodeError se produit pendant read_csv dans pandas (pd.read_table ())
Quelle automatisation doit être effectuée en RPA, VBA, langage de programmation?
J'ai essayé la notification de ligne en Python
NameError: le nom global'dot_parser 'n'est pas défini et que faire quand il apparaît en python
Lors de l'utilisation d'expressions régulières en Python