Dans l'article précédent, j'ai créé un framework avec des décorateurs comme définitions de fonctions. Cette fois, en supposant que, implémentons-le avec Class. (Pas un décorateur de classe, une définition de classe pour un décorateur de fonction)
Si vous avez besoin d'une explication de "Qu'est-ce qu'un décorateur?", Un article précédent ("Qu'est-ce qu'un décorateur - créez un cadre de décorateur général pour Python" msi / items / acfa737842416580deaf #% E3% 83% 87% E3% 82% B3% E3% 83% AC% E3% 83% BC% E3% 82% BFdecorator-% E3% 81% A8% E3% 81% AF) ) Veuillez vous référer au.
"[Application des décorateurs par classe](# classe-% E3% 81% AB% E3% 82% 88% E3% 82% 8B% E3% 83% 87% E3% 82% B3% E3% 83% AC% E3 % 83% BC% E3% 82% BF% E3% 81% AE% E5% BF% 9C% E7% 94% A8) »décrit comment appliquer des décorateurs de type de classe à l'aide de l'héritage.
decorator_class_framework.py
Le décorateur doit être un objet appelable.
@my_decorator
def f(arg):
pass
La notation du décorateur est
def f(arg):
pass
f = my_decorator(f)
Est équivalent à Autrement dit, si vous définissez une classe appelée my_decorator, cette classe doit pouvoir être appelée.
La première fois que my_decorator
est appelé (f = my_decorator (f)
),` init () ʻest appelé.
Dans l'exemple ci-dessus, «init (f)» est appelé.
Ensuite, l'instance générée est affectée à f. (Notez que la valeur de retour de «__init __ ()» n'est pas affectée.)
Lorsque le f
remplacé est appelé, l'objet my_decorator
est appelé. Si vous voulez appeler un objet de classe en tant que fonction, implémentez __call__
.
sample_001.py
class my_decorator_001:
def __init__( self, func ):
print( "called __init__" )
self._func = func
def __call__( self, *args, **kwargs ):
print( "called __call__ with args:", args, "kwargs:", kwargs )
try:
ret = self._func( *args, **kwargs )
except:
raise
print( "post func" )
return ret
@my_decorator_001
def f_001( arg1 ):
print( "in f_001 with arg1:", arg1 )
f_001( "test 001" )
Résultat d'exécution 001
>>> @my_decorator_001
... def f_001( arg1 ):
... print( "in f_001 with arg1:", arg1 )
...
called __init__
>>> f_001( "test 001" )
called __call__ with args: ('test 001',) kwargs: {}
in f_001 with arg1: test 001
post func
>>>
Pensez à donner un argument à un décorateur.
@my_decorator(arg1, arg2)
def f(arg):
pass
La notation du décorateur est
def f(arg):
pass
f = my_decorator(arg1, arg2)(f)
Est équivalent à Dans la partie my_decorator (arg1, arg2)
, __init__
est appelé avec deux arguments pour créer une instance.
__Call__
est appelé avec f
comme argument pour l'instance créée.
sample_002.py
class my_decorator_002:
def __init__( self, *args, **kwargs ):
print( "called __init__ with args:", args, "kwargs:", kwargs )
self._args = args
self._kwargs = kwargs
def __call__( self, func ):
print( "called __call__ with func:", func )
def wrapper_f( *args, **kwargs ):
print( "called wrapper_f with args:", args, "kwargs:", kwargs )
try:
ret = func( *args, **kwargs )
except:
raise
print( "post func" )
return ret
return wrapper_f
@my_decorator_002( "arg1", "arg2" )
def f_002( arg1 ):
print( "in f_002 with arg1:", arg1 )
f_002( "test 002" )
Résultat d'exécution 002
>>> @my_decorator_002( "arg1", "arg2" )
... def f_002( arg1 ):
... print( "in f_002 with arg1:", arg1 )
...
called __init__ with args: ('arg1', 'arg2') kwargs: {}
called __call__ with func: <function f_002 at 0x76b326a8>
>>> f_002( "test 002" )
called wrapper_f with args: ('test 002',) kwargs: {}
in f_002 with arg1: test 002
post func
>>>
Consolidez pour travailler avec ou sans arguments.
Le moment de l'appel de «init», de l'argument de «call» et de «call» diffère selon la présence ou l'absence de l'argument.
Argument du décorateur → | Aucun argument | Avec argument(Y compris des arguments vides) |
---|---|---|
__init__() |
__init__(func) |
__init__(args,...) |
__call__() |
Lors de l'appel d'une fonction__call__(args,...) |
Lors de la décoration__call__(func) |
Il est utilisé pour déterminer que func
est un seul argument appelable. (Par conséquent, le premier argument du décorateur créé dans cet article ne peut pas être un autre objet appelable.)
Spécifiez également @ wraps
.
(Pour @ wraps
, consultez l'article précédent," [Final Finishing-Making a Python Decorator Framework](https://qiita.com/msi/items/acfa737842416580deaf#%E6%9C%] 80% E5% BE% 8C% E3% 81% AE% E4% BB% 95% E4% B8% 8A% E3% 81% 92) "
sample_003.py
from functools import wraps
class my_decorator_003:
def __init__( self, *args, **kwargs ):
print( "called __init__ with args:", args, "kwargs:", kwargs )
self._func = None
self._args = []
self._kwargs = {}
if len(args) == 1 and callable(args[0]):
self._func = self._my_decorator( args[0] )
else:
self._args = args
self._kwargs = kwargs
def __call__( self, *args, **kwargs ):
print( "called __call__ with args:", args, "kwargs:", kwargs )
if self._func is None:
if len(args) == 1 and callable(args[0]):
self._func = self._my_decorator( args[0] )
return self._func
else:
try:
ret = self._func( *args, **kwargs )
except:
raise
return ret
def _my_decorator( self, func ):
print( "called _my_decorator with func:", func )
@wraps(func)
def wrapper_f( *args, **kwargs ):
print( "called wrapper_f with",
"args:", args, "kwargs:", kwargs,
"priv args:", self._args, "kwargs:", self._kwargs )
try:
ret = func( *args, **kwargs )
except:
raise
print( "post func" )
return ret
return wrapper_f
def f_003_0( arg1 ):
"""Doc Test"""
print( "in f_003_0 with arg1:", arg1 )
@my_decorator_003
def f_003_1( arg1 ):
"""Doc Test"""
print( "in f_003_1 with arg1:", arg1 )
@my_decorator_003( "arg1", arg2="arg2_str" )
def f_003_2( arg1 ):
"""Doc Test"""
print( "in f_003_2 with arg1:", arg1 )
@my_decorator_003()
def f_003_3( arg1 ):
"""Doc Test"""
print( "in f_003_3 with arg1:", arg1 )
f_003_0( "test 003" )
f_003_1( "test 003" )
f_003_2( "test 003" )
f_003_3( "test 003" )
Résultat d'exécution 003
>>> def f_003_0( arg1 ):
... """Doc Test"""
... print( "in f_003_0 with arg1:", arg1 )
...
>>> @my_decorator_003
... def f_003_1( arg1 ):
... """Doc Test"""
... print( "in f_003_1 with arg1:", arg1 )
...
called __init__ with args: (<function f_003_1 at 0x7697b540>,) kwargs: {}
called _my_decorator with func: <function f_003_1 at 0x7697b540>
>>> @my_decorator_003( "arg1", arg2="arg2_str" )
... def f_003_2( arg1 ):
... """Doc Test"""
... print( "in f_003_2 with arg1:", arg1 )
...
called __init__ with args: ('arg1',) kwargs: {'arg2': 'arg2_str'}
called __call__ with args: (<function f_003_2 at 0x7697b5d0>,) kwargs: {}
called _my_decorator with func: <function f_003_2 at 0x7697b5d0>
>>> @my_decorator_003()
... def f_003_3( arg1 ):
... """Doc Test"""
... print( "in f_003_3 with arg1:", arg1 )
...
called __init__ with args: () kwargs: {}
called __call__ with args: (<function f_003_3 at 0x7697b6f0>,) kwargs: {}
called _my_decorator with func: <function f_003_3 at 0x7697b6f0>
>>> f_003_0( "test 003" )
in f_003_0 with arg1: test 003
>>> f_003_1( "test 003" )
called __call__ with args: ('test 003',) kwargs: {}
called wrapper_f with args: ('test 003',) kwargs: {} priv args: [] kwargs: {}
in f_003_1 with arg1: test 003
post func
>>> f_003_2( "test 003" )
called wrapper_f with args: ('test 003',) kwargs: {} priv args: ('arg1',) kwargs: {'arg2': 'arg2_str'}
in f_003_2 with arg1: test 003
post func
>>> f_003_3( "test 003" )
called wrapper_f with args: ('test 003',) kwargs: {} priv args: () kwargs: {}
in f_003_3 with arg1: test 003
post func
>>>
C'est presque complet avec sample_003.py
, mais avec le décorateur de classe, une dernière chose à noter.
Décorons une telle fonction en utilisant sample_003.py
.
sample_003_2.py
@my_decorator_003
def f_003_4():
print( "called:", f_003_4.__name__ )
Quand vous faites cela ...
Résultat d'exécution
>>> @my_decorator_003
... def f_003_4():
... print( "called:", f_003_4.__name__ )
...
called __init__ with args: (<function f_003_4 at 0x76927618>,) kwargs: {}
called _my_decorator with func: <function f_003_4 at 0x76927618>
>>> f_003_4()
called __call__ with args: () kwargs: {}
called wrapper_f with args: () kwargs: {} priv args: [] kwargs: {}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 20, in __call__
File "<stdin>", line 32, in wrapper_f
File "<stdin>", line 3, in f_003_4
AttributeError: 'my_decorator_003' object has no attribute '__name__'
>>> def f_003_5():
... print( "called:", f_003_5.__name__ )
...
>>> f_003_5()
called: f_003_5
>>>
ʻAttributeError: l'objet 'mon_décorateur_003' n'a pas d'attribut '__ nom __' s'affiche, et j'obtiens une erreur disant que l'attribut
name` n'existe pas. Bien sûr, si vous le définissez et y faites référence sans décorateur, le résultat de l'exécution ci-dessus sera affiché.
La classe n'a pas l'attribut __name__
, et si vous essayez de l'enregistrer avec @ wrap
, elle ne sera pas créée automatiquement.
Doit être ajouté explicitement.
De plus, si vous appelez _my_decorator
à l'intérieur de __init__
, il n'y a pas de __doc__
à ce stade, alors ajoutez-le aussi explicitement.
sample_004.py
from functools import wraps
class my_decorator_004:
def __init__( self, *args, **kwargs ):
print( "called __init__ with args:", args, "kwargs:", kwargs )
self._func = None
self._args = []
self._kwargs = {}
if len(args) == 1 and callable(args[0]):
self._func = self._my_decorator( args[0] )
else:
self._args = args
self._kwargs = kwargs
def __call__( self, *args, **kwargs ):
print( "called __call__ with args:", args, "kwargs:", kwargs )
if self._func is None:
if len(args) == 1 and callable(args[0]):
self._func = self._my_decorator( args[0] )
return self._func
else:
try:
ret = self._func( *args, **kwargs )
except:
raise
return ret
def _my_decorator( self, func ):
print( "called _my_decorator with func:", func )
@wraps(func)
def wrapper_f( *args, **kwargs ):
print( "called wrapper_f with",
"args:", args, "kwargs:", kwargs,
"priv args:", self._args, "kwargs:", self._kwargs )
try:
ret = func( *args, **kwargs )
except:
raise
print( "post func" )
return ret
# wrapper_Dans f__name__Quand__doc__En fonctionnement
#Retirez le setattr ci-dessous
setattr( self, "__name__", wrapper_f.__name__ )
setattr( self, "__doc__", wrapper_f.__doc__ )
return wrapper_f
def f_004_0( arg1 ):
"""Doc Test 0"""
print( "in f_004_0 with arg1:", arg1 )
print( "__name__:", f_004_0.__name__ )
print( "__doc__:", f_004_0.__doc__ )
@my_decorator_004
def f_004_1( arg1 ):
"""Doc Test 1"""
print( "in f_004_1 with arg1:", arg1 )
print( "__name__:", f_004_1.__name__ )
print( "__doc__:", f_004_1.__doc__ )
@my_decorator_004( "arg1", arg2="arg2_str" )
def f_004_2( arg1 ):
"""Doc Test 2"""
print( "in f_004_2 with arg1:", arg1 )
print( "__name__:", f_004_2.__name__ )
print( "__doc__:", f_004_2.__doc__ )
@my_decorator_004()
def f_004_3( arg1 ):
"""Doc Test 3"""
print( "in f_004_3 with arg1:", arg1 )
print( "__name__:", f_004_3.__name__ )
print( "__doc__:", f_004_3.__doc__ )
f_004_0( "test 004" )
f_004_1( "test 004" )
f_004_2( "test 004" )
f_004_3( "test 004" )
Résultat d'exécution
>>> def f_004_0( arg1 ):
... """Doc Test 0"""
... print( "in f_004_0 with arg1:", arg1 )
... print( "__name__:", f_004_0.__name__ )
... print( "__doc__:", f_004_0.__doc__ )
...
>>> @my_decorator_004
... def f_004_1( arg1 ):
... """Doc Test 1"""
... print( "in f_004_1 with arg1:", arg1 )
... print( "__name__:", f_004_1.__name__ )
... print( "__doc__:", f_004_1.__doc__ )
...
called __init__ with args: (<function f_004_1 at 0x768fd420>,) kwargs: {}
called _my_decorator with func: <function f_004_1 at 0x768fd420>
>>> @my_decorator_004( "arg1", arg2="arg2_str" )
... def f_004_2( arg1 ):
... """Doc Test 2"""
... print( "in f_004_2 with arg1:", arg1 )
... print( "__name__:", f_004_2.__name__ )
... print( "__doc__:", f_004_2.__doc__ )
...
called __init__ with args: ('arg1',) kwargs: {'arg2': 'arg2_str'}
called __call__ with args: (<function f_004_2 at 0x768fd540>,) kwargs: {}
called _my_decorator with func: <function f_004_2 at 0x768fd540>
>>> @my_decorator_004()
... def f_004_3( arg1 ):
... """Doc Test 3"""
... print( "in f_004_3 with arg1:", arg1 )
... print( "__name__:", f_004_3.__name__ )
... print( "__doc__:", f_004_3.__doc__ )
...
called __init__ with args: () kwargs: {}
called __call__ with args: (<function f_004_3 at 0x768fd618>,) kwargs: {}
called _my_decorator with func: <function f_004_3 at 0x768fd618>
>>> f_004_0( "test 004" )
in f_004_0 with arg1: test 004
__name__: f_004_0
__doc__: Doc Test 0
>>> f_004_1( "test 004" )
called __call__ with args: ('test 004',) kwargs: {}
called wrapper_f with args: ('test 004',) kwargs: {} priv args: [] kwargs: {}
in f_004_1 with arg1: test 004
__name__: f_004_1
__doc__: Doc Test 1
post func
>>> f_004_2( "test 004" )
called wrapper_f with args: ('test 004',) kwargs: {} priv args: ('arg1',) kwargs: {'arg2': 'arg2_str'}
in f_004_2 with arg1: test 004
__name__: f_004_2
__doc__: Doc Test 2
post func
>>> f_004_3( "test 004" )
called wrapper_f with args: ('test 004',) kwargs: {} priv args: () kwargs: {}
in f_004_3 with arg1: test 004
__name__: f_004_3
__doc__: Doc Test 3
post func
>>>
Cependant, comme je l'ai écrit dans le commentaire, si vous devez utiliser __name__
ou __doc__
danswrapper_f ()
, n'utilisez passetattr ()
et gérez-le vous-même. Est requis.
En implémentant le décorateur dans une classe au lieu d'une fonction, les applications suivantes sont possibles.
sample_005.py
from functools import wraps
class My_Base:
def __init__( self ):
self._my_string = "This is Base Class"
def getstr( self ):
return self._my_string
def putstr( self, string="" ):
self._my_string = string
class my_decorator_005(My_Base):
def __init__( self, *args, **kwargs ):
super().__init__()
self._func = None
self._args = []
self._kwargs = {}
if len(args) == 1 and callable(args[0]):
self._func = self._my_decorator( args[0] )
else:
self._args = args
self._kwargs = kwargs
def __call__( self, *args, **kwargs ):
if self._func is None:
if len(args) == 1 and callable(args[0]):
self._func = self._my_decorator( args[0] )
return self._func
else:
try:
ret = self._func( *args, **kwargs )
except:
raise
return ret
def _my_decorator( self, func ):
@wraps(func)
def wrapper_f( *args, **kwargs ):
print( "called wrapper_f with",
"args:", args, "kwargs:", kwargs,
"priv args:", self._args, "kwargs:", self._kwargs )
try:
ret = func( *args, **kwargs )
except:
raise
return ret
# wrapper_Dans f__name__Quand__doc__En fonctionnement
#Supprimez le setattr ci-dessous
setattr( self, "__name__", wrapper_f.__name__ )
setattr( self, "__doc__", wrapper_f.__doc__ )
return wrapper_f
@my_decorator_005
def f_005(arg):
print( arg )
f_005( 'test 005' )
print( f_005.getstr() )
f_005.putstr( "new string" )
print( f_005.getstr() )
Résultat d'exécution
$ python sample_005.py
called wrapper_f with args: ('test 005',) kwargs: {} priv args: [] kwargs: {}
test 005
This is Base Class
new string
$
sample_005.py
est un exemple de création d'un décorateur en héritant d'une super classe, et la méthode de la super classe peut être appelée à partir de la fonction cible (en fait une instance de classe).
(Bien que j'aurais dû le définir comme une fonction, je me sens mal à l'aise qu'il s'agisse d'une instance de classe, mais lorsque j'implémente un décorateur dans une classe, le nom de la fonction pointe toujours vers l'instance de classe.)
L'exemple suivant «sample_006.py» est un exemple de création d'un nouveau décorateur en héritant du décorateur existant. Une sous-classe implémente _my_decorator ().
sample_006.py
from functools import wraps
class my_decorator_006:
def __init__( self, *args, **kwargs ):
self._func = None
self._args = []
self._kwargs = {}
if len(args) == 1 and callable(args[0]):
self._func = self._my_decorator( args[0] )
else:
self._args = args
self._kwargs = kwargs
print( "args and kwargs:", self._args, self._kwargs )
def __call__( self, *args, **kwargs ):
if self._func is None:
if len(args) == 1 and callable(args[0]):
self._func = self._my_decorator( args[0] )
return self._func
else:
try:
ret = self._func( *args, **kwargs )
except:
raise
return ret
def _my_decorator( self, func ):
# _my_decorator()Est implémenté dans une sous-classe
return func
# my_decorator_Hériter 006 et définir une nouvelle classe de décorateur
class new_my_decorator(my_decorator_006):
def __init__( self, *args, **kwargs ):
super().__init__( *args, **kwargs )
#Super classe_my_decorator()Passer outre
def _my_decorator( self, func ):
@wraps(func)
def wrapper_f( *args, **kwargs ):
print( "called wrapper_f with",
"args:", args, "kwargs:", kwargs,
"priv args:", self._args, "kwargs:", self._kwargs )
try:
ret = func( *args, **kwargs )
except:
raise
return ret
# wrapper_Dans f__name__Quand__doc__En fonctionnement
#Retirez le setattr ci-dessous
setattr( self, "__name__", wrapper_f.__name__ )
setattr( self, "__doc__", wrapper_f.__doc__ )
return wrapper_f
@new_my_decorator
def f_006_1(arg):
print( arg )
@new_my_decorator()
def f_006_2(arg):
print( arg )
@new_my_decorator( "new_my_decorator with arg")
def f_006_3(arg):
print( arg )
print( "calling f_006s" )
f_006_1( 'test f_006_1' )
f_006_2( 'test f_006_2' )
f_006_3( 'test f_006_3' )
Résultat d'exécution
$ python sample_006.py
args and kwargs: () {}
args and kwargs: ('new_my_decorator with arg',) {}
calling f_006s
called wrapper_f with args: ('test f_006_1',) kwargs: {} priv args: [] kwargs: {}
test f_006_1
called wrapper_f with args: ('test f_006_2',) kwargs: {} priv args: () kwargs: {}
test f_006_2
called wrapper_f with args: ('test f_006_3',) kwargs: {} priv args: ('new_my_decorator with arg',) kwargs: {}
test f_006_3
$
En utilisant l'héritage de classe, les superclasses peuvent absorber la différence d'appels avec ou sans arguments, et les sous-classes peuvent se concentrer sur l'implémentation de la décoration.
__init __ ()
et __ call __ ()
en fonction de la présence ou de l'absence d'arguments.decorator_class_framework.py
decorator_class_framework.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
###########################################
#Décorateur(decorator)
###########################################
from functools import wraps
class my_decorator_base:
def __init__( self, *args, **kwargs ):
#func Jugement d'argument et stockage d'argument
self._func = None
self._args = []
self._kwargs = {}
if len(args) == 1 and callable(args[0]):
#Lorsqu'un décorateur sans argument est appelé
self._func = self._wrapper( args[0] )
else:
#Lorsqu'un décorateur avec des arguments est appelé
self._args = args
self._kwargs = kwargs
def __call__( self, *args, **kwargs ):
#Jugé par la présence ou l'absence de l'argument func
if self._func is None:
if len(args) == 1 and callable(args[0]):
#Lorsqu'un décorateur avec des arguments est appelé
self._func = self._wrapper( args[0] )
return self._func
else:
#Lorsqu'un décorateur sans argument est appelé
try:
ret = self._func( *args, **kwargs )
except:
raise
return ret
def _wrapper( self, func ):
# _wrapper()Est implémenté dans une sous-classe
@wraps
def wrapper_f( *args, **kwargs ):
return func( *args, **kwargs )
return wrapper_f
class my_decorator(my_decorator_base):
"""
for doctest
>>> @my_decorator
... def f1( arg1 ):
... print( arg1 )
...
>>> @my_decorator('mytest1')
... def f2( arg2 ):
... print( arg2 )
...
>>> @my_decorator
... def f3( arg1 ):
... print( arg1 )
... a = 1/0
...
>>> @my_decorator('mytest2')
... def f4( arg2 ):
... print( arg2 )
... a = 1/0
...
>>> try:
... f1( "Hello, World! #1" )
... except:
... print( "error #1" )
...
Le pré-traitement est ici
called wrapper_f with args: ('Hello, World! #1',) kwargs: {} priv args: [] kwargs: {}
Hello, World! #1
Le post-traitement est ici
>>> try:
... f2( "Hello, World! #2" )
... except:
... print( "error #2" )
...
Le pré-traitement est ici
called wrapper_f with args: ('Hello, World! #2',) kwargs: {} priv args: ('mytest1',) kwargs: {}
Hello, World! #2
Le post-traitement est ici
>>> try:
... f3( "Hello, World! #3" )
... except:
... print( "error #3" )
...
Le pré-traitement est ici
called wrapper_f with args: ('Hello, World! #3',) kwargs: {} priv args: [] kwargs: {}
Hello, World! #3
error #3
>>> try:
... f4( "Hello, World! #4" )
... except:
... print( "error #4" )
...
Le pré-traitement est ici
called wrapper_f with args: ('Hello, World! #4',) kwargs: {} priv args: ('mytest2',) kwargs: {}
Hello, World! #4
error #4
>>>
"""
def __init__( self, *args, **kwargs ):
super().__init__( *args, **kwargs )
def _wrapper( self, func ):
"""Organe d'appel du décorateur"""
@wraps(func)
def wrapper_f( *args, **kwargs ):
#Le pré-traitement est ici
print( "Le pré-traitement est ici" )
print( "called wrapper_f with",
"args:", args, "kwargs:", kwargs,
"priv args:", self._args, "kwargs:", self._kwargs )
try:
ret = func( *args, **kwargs )
except:
raise
#Le post-traitement est ici
print( "Le post-traitement est ici" )
return ret
# wrapper_Dans f__name__Quand__doc__En fonctionnement
#Retirez le setattr ci-dessous
setattr( self, "__name__", wrapper_f.__name__ )
setattr( self, "__doc__", wrapper_f.__doc__ )
return wrapper_f
###########################################
# unitttest
###########################################
import unittest
from io import StringIO
import sys
class Test_My_Decorator(unittest.TestCase):
def setUp(self):
self.saved_stdout = sys.stdout
self.stdout = StringIO()
sys.stdout = self.stdout
def tearDown(self):
sys.stdout = self.saved_stdout
def test_decorator_noarg(self):
@my_decorator
def t1(arg0):
print( arg0 )
t1("test_decorator_noarg")
self.assertEqual(self.stdout.getvalue(),
"Le pré-traitement est ici\n"
"called wrapper_f with args: ('test_decorator_noarg',) kwargs: {} priv args: [] kwargs: {}\n"
"test_decorator_noarg\n"
"Le post-traitement est ici\n"
)
def test_decorator_witharg(self):
@my_decorator('with arg')
def t1(arg0):
print( arg0 )
t1("test_decorator_witharg")
self.assertEqual(self.stdout.getvalue(),
"Le pré-traitement est ici\n"
"called wrapper_f with args: ('test_decorator_witharg',) kwargs: {} priv args: ('with arg',) kwargs: {}\n"
"test_decorator_witharg\n"
"Le post-traitement est ici\n"
)
def test_functionname(self):
@my_decorator
def t1():
return t1.__name__
f_name = t1()
self.assertEqual( f_name, "t1" )
def test_docattribute(self):
@my_decorator
def t1():
"""Test Document"""
pass
self.assertEqual( t1.__doc__, "Test Document" )
###########################################
# main
###########################################
if __name__ == '__main__':
@my_decorator
def f1( arg1 ):
print( arg1 )
@my_decorator('mytest1')
def f2( arg2 ):
print( arg2 )
@my_decorator
def f3( arg1 ):
print( arg1 )
a = 1/0
@my_decorator('mytest2')
def f4( arg2 ):
print( arg2 )
a = 1/0
try:
f1( "Hello, World! #1" )
except:
print( "error #1" )
try:
f2( "Hello, World! #2" )
except:
print( "error #2" )
try:
f3( "Hello, World! #3" )
except:
print( "error #3" )
try:
f4( "Hello, World! #4" )
except:
print( "error #4" )
import doctest
doctest.testmod()
unittest.main()
Résultat d'exécution
$ python decorator_class_framework.py
Le pré-traitement est ici
called wrapper_f with args: ('Hello, World! #1',) kwargs: {} priv args: [] kwargs: {}
Hello, World! #1
Le post-traitement est ici
Le pré-traitement est ici
called wrapper_f with args: ('Hello, World! #2',) kwargs: {} priv args: ('mytest1',) kwargs: {}
Hello, World! #2
Le post-traitement est ici
Le pré-traitement est ici
called wrapper_f with args: ('Hello, World! #3',) kwargs: {} priv args: [] kwargs: {}
Hello, World! #3
error #3
Le pré-traitement est ici
called wrapper_f with args: ('Hello, World! #4',) kwargs: {} priv args: ('mytest2',) kwargs: {}
Hello, World! #4
error #4
....
----------------------------------------------------------------------
Ran 4 tests in 0.003s
OK
$
unittest Résultat d'exécution
$ python -m unittest -v decorator_class_framework.py
test_decorator_noarg (decorator_class_framework.Test_My_Decorator) ... ok
test_decorator_witharg (decorator_class_framework.Test_My_Decorator) ... ok
test_docattribute (decorator_class_framework.Test_My_Decorator) ... ok
test_functionname (decorator_class_framework.Test_My_Decorator) ... ok
----------------------------------------------------------------------
Ran 4 tests in 0.005s
OK
$
Recommended Posts