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.
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)
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.
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)
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.
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.
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)
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