Mémo d'opération de décorateur Python

Lorsque vous étudiez la programmation Python à l'aide de décorateurs, même si vous pouvez la comprendre sur place, vous l'oublierez vite. Donc, cette fois, j'ai essayé de faire fonctionner l'exemple d'application qui ajoute dynamiquement une méthode et j'ai noté les valeurs de chaque paramètre.

■ Utilisez des décorateurs pour ajouter dynamiquement des méthodes

(1) Exemple de programme

Il s'agit d'un exemple de programme qui décore les méthodes (func1, func2) qui ont des arguments.

sample1.py


import sys
import json
import logging

logging.basicConfig()
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)


def api_method(api_name):
    def _api_method(fn):
        log.debug("fn={}".format(fn))
        log.debug("api_name={}".format(api_name))
        setattr(fn, '__api_name__', api_name)
        return fn
    return _api_method

class Sample(object):
    def __init__(self):
        log.debug(json.dumps(dir(self), sort_keys=False, indent=4))

        self._api_methods = {}
        for method_name in dir(self):
            method = getattr(self, method_name)
            try:
                name = getattr(method, '__api_name__')
                msg = 'API method {0} registered'.format(name)
                log.debug(msg)
                self._api_methods[name] = method
            except AttributeError:
                pass

        log.debug("_api_methods=[%s]"%self._api_methods)

    @api_method('func1')
    def _func1(self, params):
        print ("*** func1 : params=[%s]"%params)
        return "func1 is done!"

    @api_method('func2')
    def _func2(self, params):
        print ("*** func2 : params=[%s]"%params)
        return "func2 is done!"


if __name__ == '__main__':
    args = sys.argv
    if len(args) == 3:
        method = args[1]
        params = args[2]

    m = Sample()
    result = m._api_methods[method](params)
    print ("*** result=[%s]"%result)

(2) Déplacez-le réellement

Commençons par déplacer la méthode func1

$ python sample1.py func1 aaa
DEBUG:__main__:fn=<function Sample._func1 at 0x10dde60d0>
DEBUG:__main__:api_name=func1
DEBUG:__main__:fn=<function Sample._func2 at 0x10dde6158>
DEBUG:__main__:api_name=func2
DEBUG:__main__:[
    "__class__",
    "__delattr__",
    "__dict__",
    "__dir__",
    "__doc__",
    "__eq__",
    "__format__",
    "__ge__",
    "__getattribute__",
    "__gt__",
    "__hash__",
    "__init__",
    "__init_subclass__",
    "__le__",
    "__lt__",
    "__module__",
    "__ne__",
    "__new__",
    "__reduce__",
    "__reduce_ex__",
    "__repr__",
    "__setattr__",
    "__sizeof__",
    "__str__",
    "__subclasshook__",
    "__weakref__",
    "_func1",
    "_func2"
]
DEBUG:__main__:API method func1 registered
DEBUG:__main__:API method func2 registered
DEBUG:__main__:_api_methods=[{'func1': <bound method Sample._func1 of <__main__.Sample object at 0x10ddde898>>, 'func2': <bound method Sample._func2 of <__main__.Sample object at 0x10ddde898>>}]
*** func1 : params=[aaa]
*** result=[func1 is done!]

Ensuite, essayez d'exécuter la méthode func2

$ python sample1.py func2 bbb
DEBUG:__main__:fn=<function Sample._func1 at 0x10f9790d0>
DEBUG:__main__:api_name=func1
DEBUG:__main__:fn=<function Sample._func2 at 0x10f979158>
DEBUG:__main__:api_name=func2
DEBUG:__main__:[
    "__class__",
    "__delattr__",
    "__dict__",
    "__dir__",
    "__doc__",
    "__eq__",
    "__format__",
    "__ge__",
    "__getattribute__",
    "__gt__",
    "__hash__",
    "__init__",
    "__init_subclass__",
    "__le__",
    "__lt__",
    "__module__",
    "__ne__",
    "__new__",
    "__reduce__",
    "__reduce_ex__",
    "__repr__",
    "__setattr__",
    "__sizeof__",
    "__str__",
    "__subclasshook__",
    "__weakref__",
    "_func1",
    "_func2"
]
DEBUG:__main__:API method func1 registered
DEBUG:__main__:API method func2 registered
DEBUG:__main__:_api_methods=[{'func1': <bound method Sample._func1 of <__main__.Sample object at 0x10f971908>>, 'func2': <bound method Sample._func2 of <__main__.Sample object at 0x10f971908>>}]
*** func2 : params=[bbb]
*** result=[func2 is done!]

J'ai pu le démarrer correctement.

■ Essayez d'ajouter des méthodes de manière dynamique sans utiliser de décorateurs

(1) Exemple de programme

Il s'agit d'un exemple de programme qui fonctionne de la même manière sans utiliser de décorations.

sample2.py


import sys
import json
import logging

logging.basicConfig()
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)


class Sample(object):
    def __init__(self):
        log.debug(json.dumps(dir(self), sort_keys=False, indent=4))

    def func1(self, params):
        print ("*** func1 : params=[%s]"%params)
        return "func1 is done!"

    def func2(self, params):
        print ("*** func2 : params=[%s]"%params)
        return "func2 is done!"


if __name__ == '__main__':
    args = sys.argv
    if len(args) == 3:
        method = args[1]
        params = args[2]

    m = Sample()
    meth = getattr(m, method, None)
    if meth:
        result = meth(params)
        print ("*** result=[%s]"%result)

(2) Déplacez-le réellement

Commençons par déplacer la méthode func1

$ python sample2.py func1 aaa
DEBUG:__main__:[
    "__class__",
    "__delattr__",
    "__dict__",
    "__dir__",
    "__doc__",
    "__eq__",
    "__format__",
    "__ge__",
    "__getattribute__",
    "__gt__",
    "__hash__",
    "__init__",
    "__init_subclass__",
    "__le__",
    "__lt__",
    "__module__",
    "__ne__",
    "__new__",
    "__reduce__",
    "__reduce_ex__",
    "__repr__",
    "__setattr__",
    "__sizeof__",
    "__str__",
    "__subclasshook__",
    "__weakref__",
    "func1",
    "func2"
]
*** func1 : params=[aaa]
*** result=[func1 is done!]

Ensuite, essayez d'exécuter la méthode func2

$ python sample2.py func2 bbb
DEBUG:__main__:[
    "__class__",
    "__delattr__",
    "__dict__",
    "__dir__",
    "__doc__",
    "__eq__",
    "__format__",
    "__ge__",
    "__getattribute__",
    "__gt__",
    "__hash__",
    "__init__",
    "__init_subclass__",
    "__le__",
    "__lt__",
    "__module__",
    "__ne__",
    "__new__",
    "__reduce__",
    "__reduce_ex__",
    "__repr__",
    "__setattr__",
    "__sizeof__",
    "__str__",
    "__subclasshook__",
    "__weakref__",
    "func1",
    "func2"
]
*** func2 : params=[bbb]
*** result=[func2 is done!]

Cela a également pu démarrer correctement.

■ Poursuite de l'expansion

Lors de la création d'une application qui ajoute des méthodes de manière dynamique, je pense qu'il est plus simple d'écrire du code sans créer de décorateur, mais quand est-il souhaitable d'utiliser un décorateur? Je pense que c'est juste dans le but de décorer la méthode, comme l'ajout d'une instruction DEBUG, alors je l'ai étendue davantage.

(1) Exemple de programme

sample3.py


import sys
import json
import logging

logging.basicConfig()
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)


def api_method(api_name):
    def _api_method(fn):
        log.debug("fn={}".format(fn))
        log.debug("api_name={}".format(api_name))
        def _wrap(*args, **kwargs):
            log.debug("--Prétraitement-- [{}]".format(api_name))
            ret = fn(*args, **kwargs)
            log.debug("--Post-traitement-- [{}]".format(api_name))
            return ret
        return _wrap
    return _api_method

class Sample(object):
    def __init__(self):
        log.debug(json.dumps(dir(self), sort_keys=False, indent=4))

    @api_method('func1')
    def func1(self, params):
        print ("*** func1 : params=[%s]"%params)
        return "func1 is done!"

    @api_method('func2')
    def func2(self, params):
        print ("*** func2 : params=[%s]"%params)
        return "func2 is done!"


if __name__ == '__main__':
    args = sys.argv
    if len(args) == 3:
        method = args[1]
        params = args[2]

    m = Sample()
    meth = getattr(m, method, None)
    if meth:
        result = meth(params)
        print ("*** result=[%s]"%result)

(2) Déplacez-le réellement

Commençons par déplacer la méthode func1

$ python sample3.py func1 aaa
DEBUG:__main__:fn=<function Sample.func1 at 0x10aba10d0>
DEBUG:__main__:api_name=func1
DEBUG:__main__:fn=<function Sample.func2 at 0x10aba11e0>
DEBUG:__main__:api_name=func2
DEBUG:__main__:[
    "__class__",
    "__delattr__",
    "__dict__",
    "__dir__",
    "__doc__",
    "__eq__",
    "__format__",
    "__ge__",
    "__getattribute__",
    "__gt__",
    "__hash__",
    "__init__",
    "__init_subclass__",
    "__le__",
    "__lt__",
    "__module__",
    "__ne__",
    "__new__",
    "__reduce__",
    "__reduce_ex__",
    "__repr__",
    "__setattr__",
    "__sizeof__",
    "__str__",
    "__subclasshook__",
    "__weakref__",
    "func1",
    "func2"
]
DEBUG:__main__:--Prétraitement-- [func1]
*** func1 : params=[aaa]
DEBUG:__main__:--Post-traitement-- [func1]
*** result=[func1 is done!]

Ensuite, essayez d'exécuter la méthode func2

$ python sample3.py func2 bbb
DEBUG:__main__:fn=<function Sample.func1 at 0x106a1d0d0>
DEBUG:__main__:api_name=func1
DEBUG:__main__:fn=<function Sample.func2 at 0x106a1d1e0>
DEBUG:__main__:api_name=func2
DEBUG:__main__:[
    "__class__",
    "__delattr__",
    "__dict__",
    "__dir__",
    "__doc__",
    "__eq__",
    "__format__",
    "__ge__",
    "__getattribute__",
    "__gt__",
    "__hash__",
    "__init__",
    "__init_subclass__",
    "__le__",
    "__lt__",
    "__module__",
    "__ne__",
    "__new__",
    "__reduce__",
    "__reduce_ex__",
    "__repr__",
    "__setattr__",
    "__sizeof__",
    "__str__",
    "__subclasshook__",
    "__weakref__",
    "func1",
    "func2"
]
DEBUG:__main__:--Prétraitement-- [func2]
*** func2 : params=[bbb]
DEBUG:__main__:--Post-traitement-- [func2]
*** result=[func2 is done!]

Cela fonctionne bien maintenant. c'est tout

Recommended Posts

Mémo d'opération de décorateur Python
Mémo Python
mémo python
Mémo Python
Mémo Python
Mémo Python
[Python] Mémo d'opération de pandas DataFrame
[Python] Mémo sur le dictionnaire
Remarque: décorateur Python
mémo débutant python (9.2-10)
[python] Opération vectorielle
mémo débutant python (9.1)
★ Mémo ★ Python Iroha
Fonctionnement du système d'exploitation Python
[Python] Mémo EDA
Mémo opérateur Python 3
[Python] Opération de matrice
[Mon mémo] python
Mémo de métaclasse Python3
[Python] Mémo de fond de carte
Décorateur de fonction Python
Mémo débutant Python (2)
[Python] Mémo Numpy
[Mémo du débutant Python] chaîne de caractères python, opération de chemin
[Python] Opération d'énumération
Classe Python (mémo d'apprentissage Python ⑦)
installation de python openCV (mémo)
Module Python (mémo d'apprentissage Python ④)
Mémo de visualisation par Python
Mémo du package de test Python
[Python] Mémo sur les fonctions
notes d'utilisation du décorateur python
mémo d'expression régulière python
Mémo de type Liste / Dictionnaire Python3
[Mémo] Tri de liste Python3
Astuces Python (mon mémo)
[Python] Mémo sur les erreurs
Mémo de script DynamoDB (Python)
Résumé des opérations d'annuaire Python
Mémo de base Python - Partie 2
livre de recettes python Memo
Obstacle à la logique Python
Notes de commande de base Python
Mémo du didacticiel Python OpenCV
Mémo de grammaire de base Python
Mémo de l'API TensorFlow (Python)
liens de mémo utiles python
J'ai essayé Python> décorateur
Mémo de base Python - Partie 1
Élément de mémo Python efficace 3
Mémo Python d'énumération approximative
[python] Opération de tranche de tableau
Mémo Python (pour moi): Array
Mémo de mesure du temps d'exécution Python
Mémo graphique Twitter avec Python
[Line / Python] Mémo d'implémentation Beacon
Opération S3 avec python boto3
Mémo tranche python et rubis