Im vorherigen Artikel habe ich ein Framework mit Dekoratoren als Funktionsdefinitionen erstellt. Nehmen wir diesmal an, dass wir es mit Class implementieren. (Kein Klassendekorateur, eine Klassendefinition für einen Funktionsdekorateur)
Wenn Sie eine Erklärung aus "Was ist ein Dekorateur?" Benötigen, Ein vorheriger Beitrag ("Was ist ein Dekorateur - Erstellen Sie ein universelles Dekorationsframework für 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) ) Bitte wende dich an die.
"[Dekorateure nach Klasse anwenden](# Klasse-% 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) “beschreibt, wie Klassentypdekorateure mithilfe der Vererbung angewendet werden.
decorator_class_framework.py
Der Dekorateur muss ein aufrufbares Objekt sein.
@my_decorator
def f(arg):
pass
Die Dekorationsnotation ist
def f(arg):
pass
f = my_decorator(f)
Ist äquivalent zu Wenn Sie also eine Klasse mit dem Namen my_decorator definieren, muss diese Klasse aufrufbar sein.
Wenn zum ersten Mal "my_decorator" aufgerufen wird ("f = my_decorator (f)"), wird "init ()" aufgerufen.
Im obigen Beispiel wird "init (f)" aufgerufen.
Dann wird die generierte Instanz f zugewiesen. (Beachten Sie, dass der Rückgabewert von __init __ ()
nicht zugewiesen ist.)
Wenn das ersetzte "f" aufgerufen wird, wird das "my_decorator" -Objekt aufgerufen. Wenn Sie ein Klassenobjekt als Funktion aufrufen möchten, implementieren Sie __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" )
Ausführungsergebnis 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
>>>
Erwägen Sie, einem Dekorateur ein Argument zu geben.
@my_decorator(arg1, arg2)
def f(arg):
pass
Die Dekorationsnotation ist
def f(arg):
pass
f = my_decorator(arg1, arg2)(f)
Ist äquivalent zu Im Teil "my_decorator (arg1, arg2)" wird "init" mit zwei Argumenten aufgerufen, um eine Instanz zu erstellen.
__Call__
wird mit f
als Argument für die erstellte Instanz aufgerufen.
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" )
Ausführungsergebnis 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
>>>
Konsolidieren Sie, um mit oder ohne Argumente zu arbeiten.
Das Aufruf-Timing von "init", das Argument von "call" und "call" unterscheidet sich je nach Vorhandensein oder Fehlen des Arguments.
Dekorateurargument → | Keine Argumente | Mit Argument(Einschließlich leerer Argumente) |
---|---|---|
__init__() |
__init__(func) |
__init__(args,...) |
__call__() |
Beim Aufruf einer Funktion__call__(args,...) |
Beim Dekorieren__call__(func) |
Es wird verwendet, um zu bestimmen, dass "func" ein einzelnes aufrufbares Argument ist. (Daher kann das erste Argument des in diesem Artikel erstellten Dekorateurs kein anderes aufrufbares Objekt sein.)
Geben Sie auch "@ wraps" an. (Informationen zu "@ wraps" finden Sie im vorherigen Artikel "[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" )
Ausführungsergebnis 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
>>>
Es ist fast fertig mit sample_003.py
, aber mit dem Class Decorator noch eine Sache zu beachten.
Lassen Sie uns eine solche Funktion mit sample_003.py
dekorieren.
sample_003_2.py
@my_decorator_003
def f_003_4():
print( "called:", f_003_4.__name__ )
Wenn Sie dies tun ...
Ausführungsergebnis
>>> @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: 'my_decorator_003' Objekt hat kein Attribut '__ name __'
wird angezeigt und ich erhalte die Fehlermeldung, dass es kein Attribut __name__
gibt. Wenn Sie es ohne Dekorateur definieren und darauf verweisen, wird natürlich das obige Ausführungsergebnis angezeigt.
Die Klasse hat nicht das Attribut __name__
, und wenn Sie versuchen, es mit @ wrap
zu speichern, wird es nicht automatisch erstellt.
Muss explizit hinzugefügt werden.
Wenn Sie "_my_decorator" in "init" aufrufen, gibt es zu diesem Zeitpunkt kein "doc". Fügen Sie es daher auch explizit hinzu.
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_Innerhalb von f__name__Wann__doc__Beim Betrieb
#Entfernen Sie das Setattr unten
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" )
Ausführungsergebnis
>>> 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
>>>
Wie ich jedoch im Kommentar geschrieben habe, verwenden Sie "setattr ()" nicht und verwalten Sie es selbst, wenn Sie "name" oder "doc" in "wrapper_f ()" ausführen müssen. Wird benötigt.
Durch Implementieren des Dekorators in einer Klasse anstelle einer Funktion sind die folgenden Anwendungen möglich.
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_Innerhalb von f__name__Wann__doc__Beim Betrieb
#Entfernen Sie das Setattr unten
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() )
Ausführungsergebnis
$ 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
ist ein Beispiel für das Erstellen eines Dekorators durch Erben einer Superklasse, und die Methode der Superklasse kann von der Zielfunktion (eigentlich einer Klasseninstanz) aufgerufen werden.
(Es ist mir unangenehm, dass es sich um eine Klasseninstanz handelt, obwohl ich sie als Funktion hätte definieren sollen. Wenn ich jedoch einen Dekorator in einer Klasse implementiere, zeigt der Funktionsname immer auf die Klasseninstanz.)
Das folgende Beispiel, "sample_006.py", ist ein Beispiel für das Erstellen eines neuen Dekorators durch Erben eines vorhandenen Dekorators. Eine Unterklasse implementiert _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()Wird in einer Unterklasse implementiert
return func
# my_decorator_Erben Sie 006 und definieren Sie eine neue Dekorationsklasse
class new_my_decorator(my_decorator_006):
def __init__( self, *args, **kwargs ):
super().__init__( *args, **kwargs )
#Super Klasse_my_decorator()Überschreiben
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_Innerhalb von f__name__Wann__doc__Beim Betrieb
#Entfernen Sie das Setattr unten
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' )
Ausführungsergebnis
$ 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
$
Durch die Verwendung der Klassenvererbung können Oberklassen den Unterschied beim Aufrufen mit oder ohne Argumente absorbieren, und Unterklassen können sich auf die Implementierung der Dekoration konzentrieren.
decorator_class_framework.py
decorator_class_framework.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
###########################################
#Dekorateur(decorator)
###########################################
from functools import wraps
class my_decorator_base:
def __init__( self, *args, **kwargs ):
#func Argumenturteil und Argumentspeicherung
self._func = None
self._args = []
self._kwargs = {}
if len(args) == 1 and callable(args[0]):
#Wenn ein Dekorateur ohne Argumente aufgerufen wird
self._func = self._wrapper( args[0] )
else:
#Wenn ein Dekorateur mit Argumenten aufgerufen wird
self._args = args
self._kwargs = kwargs
def __call__( self, *args, **kwargs ):
#Gemessen am Vorhandensein oder Fehlen des Funktionsarguments
if self._func is None:
if len(args) == 1 and callable(args[0]):
#Wenn ein Dekorateur mit Argumenten aufgerufen wird
self._func = self._wrapper( args[0] )
return self._func
else:
#Wenn ein Dekorateur ohne Argumente aufgerufen wird
try:
ret = self._func( *args, **kwargs )
except:
raise
return ret
def _wrapper( self, func ):
# _wrapper()Wird in einer Unterklasse implementiert
@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" )
...
Die Vorverarbeitung ist da
called wrapper_f with args: ('Hello, World! #1',) kwargs: {} priv args: [] kwargs: {}
Hello, World! #1
Die Nachbearbeitung ist da
>>> try:
... f2( "Hello, World! #2" )
... except:
... print( "error #2" )
...
Die Vorverarbeitung ist da
called wrapper_f with args: ('Hello, World! #2',) kwargs: {} priv args: ('mytest1',) kwargs: {}
Hello, World! #2
Die Nachbearbeitung ist da
>>> try:
... f3( "Hello, World! #3" )
... except:
... print( "error #3" )
...
Die Vorverarbeitung ist da
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" )
...
Die Vorverarbeitung ist da
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 ):
"""Dekorateur Anrufkörper"""
@wraps(func)
def wrapper_f( *args, **kwargs ):
#Die Vorverarbeitung ist da
print( "Die Vorverarbeitung ist da" )
print( "called wrapper_f with",
"args:", args, "kwargs:", kwargs,
"priv args:", self._args, "kwargs:", self._kwargs )
try:
ret = func( *args, **kwargs )
except:
raise
#Die Nachbearbeitung ist da
print( "Die Nachbearbeitung ist da" )
return ret
# wrapper_Innerhalb von f__name__Wann__doc__Beim Betrieb
#Entfernen Sie das Setattr unten
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(),
"Die Vorverarbeitung ist da\n"
"called wrapper_f with args: ('test_decorator_noarg',) kwargs: {} priv args: [] kwargs: {}\n"
"test_decorator_noarg\n"
"Die Nachbearbeitung ist da\n"
)
def test_decorator_witharg(self):
@my_decorator('with arg')
def t1(arg0):
print( arg0 )
t1("test_decorator_witharg")
self.assertEqual(self.stdout.getvalue(),
"Die Vorverarbeitung ist da\n"
"called wrapper_f with args: ('test_decorator_witharg',) kwargs: {} priv args: ('with arg',) kwargs: {}\n"
"test_decorator_witharg\n"
"Die Nachbearbeitung ist da\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()
Ausführungsergebnis
$ python decorator_class_framework.py
Die Vorverarbeitung ist da
called wrapper_f with args: ('Hello, World! #1',) kwargs: {} priv args: [] kwargs: {}
Hello, World! #1
Die Nachbearbeitung ist da
Die Vorverarbeitung ist da
called wrapper_f with args: ('Hello, World! #2',) kwargs: {} priv args: ('mytest1',) kwargs: {}
Hello, World! #2
Die Nachbearbeitung ist da
Die Vorverarbeitung ist da
called wrapper_f with args: ('Hello, World! #3',) kwargs: {} priv args: [] kwargs: {}
Hello, World! #3
error #3
Die Vorverarbeitung ist da
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 Ausführungsergebnis
$ 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