En Java, par exemple, l' @Override
annotation fournit non seulement une vérification à la compilation d'un remplacement, mais constitue un excellent code d'auto-documentation.
Je cherche juste de la documentation (même si c'est un indicateur pour un vérificateur comme pylint, c'est un bonus). Je peux ajouter un commentaire ou une docstring quelque part, mais quelle est la manière idiomatique d'indiquer un remplacement en Python?
Réponses:
Sur la base de cela et de la réponse de fwc: s, j'ai créé un package installable pip https://github.com/mkorpela/overrides
De temps en temps, je finis par examiner cette question. Cela se produit principalement après avoir (à nouveau) vu le même bogue dans notre base de code: quelqu'un a oublié une classe d'implémentation "interface" en renommant une méthode dans "interface".
Eh bien, Python n'est pas Java mais Python a du pouvoir - et l'explicite est mieux qu'implicite - et il y a de vrais cas concrets dans le monde réel où cela m'aurait aidé.
Voici donc un croquis du décorateur de substitutions. Cela vérifiera que la classe donnée en paramètre a le même nom de méthode (ou quelque chose) que la méthode en cours de décoration.
Si vous pouvez penser à une meilleure solution, veuillez la poster ici!
Cela fonctionne comme suit:
et si vous faites une version défectueuse, cela déclenchera une erreur d'assertion lors du chargement de la classe:
la source
overrides
pourrait copier la docstring de la méthode surchargée si la méthode surchargée n'en a pas une.Voici une implémentation qui ne nécessite pas la spécification du nom interface_class.
la source
Si vous le souhaitez uniquement à des fins de documentation, vous pouvez définir votre propre décorateur de remplacement:
Ce n'est vraiment rien d'autre que du plaisir pour les yeux, à moins que vous ne créiez un remplacement (f) de manière à vérifier en fait un remplacement.
Mais alors, c'est Python, pourquoi l'écrire comme si c'était Java?
la source
override
décorateur.Python n'est pas Java. Il n'y a bien sûr pas vraiment de vérification à la compilation.
Je pense qu'un commentaire dans la docstring est suffisant. Cela permet à tout utilisateur de votre méthode de taper
help(obj.method)
et de voir que la méthode est une substitution.Vous pouvez également étendre explicitement une interface avec
class Foo(Interface)
, ce qui permettra aux utilisateurs de taperhelp(Interface.method)
pour avoir une idée de la fonctionnalité que votre méthode est censée fournir.la source
@Override
Java n'est pas de documenter - c'est d'attraper une erreur lorsque vous aviez l'intention de remplacer une méthode, mais que vous avez fini par en définir une nouvelle (par exemple parce que vous avez mal orthographié un nom; en Java, cela peut aussi arriver parce que vous avez utilisé la mauvaise signature, mais ce n'est pas un problème en Python - mais une faute d'orthographe l'est toujours).@Override
est la documentation en plus de la vérification du temps de compilation.Improviser sur @mkorpela bonne réponse , voici une version avec
vérifications, dénomination et objets d'erreur plus précis
Voici à quoi cela ressemble en pratique:
NotImplementedError
" non implémenté dans la classe de base "entraîne une
NotImplementedError
erreur plus descriptiveun paquet entier
NotImplementedError
" type d'implémentation attendu "entraîne une
NotImplementedError
erreur plus descriptiveun paquet entier
Le grand avantage de la réponse @mkorpela est que la vérification se produit pendant une phase d'initialisation. Le contrôle n'a pas besoin d'être "exécuté". En se référant aux exemples précédents,
class B
n'est jamais initialisé (B()
) mais leNotImplementedError
sera quand même augmenté. Cela signifie que lesoverrides
erreurs sont détectées plus tôt.la source
overrides.py
. Je ne suis pas sûr de ce que je peux améliorer de manière significative, sauf pour changer les types d'exceptions deTypeError
àNotImplementedError
.types.MethodType
. C'était une bonne idée dans votre réponse.Comme d'autres l'ont dit, contrairement à Java, il n'y a pas de balise @Overide, mais ci-dessus, vous pouvez créer les vôtres à l'aide de décorateurs, mais je suggérerais d'utiliser la méthode globale getattrib () au lieu d'utiliser le dict interne afin d'obtenir quelque chose comme ce qui suit:
Si vous le vouliez, vous pourriez attraper getattr () dans votre propre try catch, mais je pense que la méthode getattr est meilleure dans ce cas.
Cela attrape également tous les éléments liés à une classe, y compris les méthodes de classe et les vairables
la source
Sur la base de la bonne réponse de @ mkorpela, j'ai écrit un package similaire ( ipromise pypi github ) qui effectue beaucoup plus de vérifications:
Supposons
A
hérite deB
etC
,B
hérite deC
.Le module ipromise vérifie que:
Si
A.f
overridesB.f
,B.f
doit exister etA
doit hériter deB
. (Ceci est la vérification du package des remplacements).Vous n'avez pas le modèle
A.f
déclare qu'il remplaceB.f
, qui déclare ensuite qu'il remplaceC.f
.A
devrait dire qu'il remplace deC.f
puisqueB
pourrait décider d'arrêter de remplacer cette méthode, et cela ne devrait pas entraîner de mises à jour en aval.Vous n'avez pas le modèle
A.f
déclare qu'il remplaceC.f
, maisB.f
ne déclare pas son remplacement.Vous n'avez pas le modèle
A.f
déclare qu'il remplaceC.f
, maisB.f
déclare qu'il remplace certainsD.f
.Il possède également diverses fonctionnalités de marquage et de vérification mettant en œuvre une méthode abstraite.
la source
Hear est le plus simple et fonctionne sous Jython avec des classes Java:
la source
Non seulement le décorateur que j'ai fait vérifier si le nom de l'attribut de remplacement dans est une superclasse de la classe dans laquelle l'attribut se trouve sans avoir à spécifier une superclasse, ce décorateur vérifie également pour s'assurer que l'attribut de remplacement doit être du même type que l'attribut remplacé attribut. Les méthodes de classe sont traitées comme des méthodes et les méthodes statiques sont traitées comme des fonctions. Ce décorateur fonctionne pour les callables, les méthodes de classe, les méthodes statiques et les propriétés.
Pour le code source, voir: https://github.com/fireuser909/override
Ce décorateur ne fonctionne que pour les classes qui sont des instances de remplacement.OverridesMeta mais si votre classe est une instance d'une métaclasse personnalisée, utilisez la fonction create_custom_overrides_meta pour créer une métaclasse compatible avec le décorateur de remplacement. Pour les tests, exécutez le module override .__ init__.
la source
En Python 2.6+ et Python 3.2+, vous pouvez le faire (en fait , simulez-le , Python ne prend pas en charge la surcharge de fonctions et la classe enfant remplace automatiquement la méthode parent). Nous pouvons utiliser des décorateurs pour cela. Mais d'abord, notez que Python
@decorators
et Java@Annotations
sont des choses totalement différentes. Le précédent est un wrapper avec du code concret tandis que le dernier est un indicateur à compilateur.Pour cela, faites d'abord
pip install multipledispatch
production:
Une chose à retenir est que puisque Python n'a pas de surcharge de fonction directement, donc même si la classe B n'hérite pas de la classe A mais a besoin de tous ces
foo
s, vous devez également utiliser @Override (bien que l'utilisation de l'alias 'Overload' semble mieux dans ce cas)la source