Seite 1 von 1
Decorators with parameters in Python
Verfasst: Dienstag 14. April 2020, 16:05
von Devanther
Hallo,
https://repl.it/@tecladocode/CP1605-Dec ... parameters
kann mir jemand erklären was dieser Code macht. Für mich unglaublich schwer zu verstehen.
Was passiert bei der Ausgabe?
Kann mir jemand erklären SCHRITT FÜR SCHRITT erklären was der Code macht?
Was macht das?
@functools.wraps(func)
Ich weiss gar nicht wo ich anfangen soll, diesen Code zu verstehen!
Kann mir jemand schrittweise durch den Code helfen, es sind paar Zeilen Code aber trotzdem sehr schwer.
Re: Decorators with parameters in Python
Verfasst: Dienstag 14. April 2020, 16:34
von __deets__
Die Dekorator-Syntax ist syntaktischer Zucker fuer das hier:
Code: Alles auswählen
def meindekorator(func):
return func # tut nix
@meindekorator
def eine_funktion():
pass
# ist exakt gleich zu dem hier:
def eine_funktion():
pass
eine_funktion = meindekorator(eine_funktion)
Ein Dekorator ist also nichts anderes als
- eine Funktion
- die ein Argument bekommt
- und deren Rueckgabe dann an Stelle des urspruenglichen Funktion an den Namen gebunden wird.
Und wenn man einem solchen Dekorator Parameter verpassen will, dann muss man
- eine Funktion mit Argumenten erstellen
- die als Rueckgabewert eine Funktion liefert, die dem Dekorator Protokoll folgt
Code: Alles auswählen
def mein_parametrisierter_dekorator(name):
def dekorator(func):
def namensausgabe(*a, **kw):
print("hallo", name)
return func(*a, **kw) # einfach den eigentlichen Funktionsaufruf machen
return namensausgabe # das wird die neue Funktion
return dekorator # hier geben wir den eigentlichen Dekorator zurueck
@mein_parametrisierter_dekorator("karl heinz")
def funktion(a, b, c):
print(a, b, c)
funktion(1, 2, "tausend")
Re: Decorators with parameters in Python
Verfasst: Dienstag 14. April 2020, 16:46
von __blackjack__
Erst einmal der Code um den es hier geht, damit man die Frage auch versteht wenn der mal nicht mehr hinter dem externen Link vorhanden ist:
Code: Alles auswählen
import functools
user = {'username': 'jose123', 'access_level': 'user'}
def user_has_permission(access_level):
def my_decorator(func):
@functools.wraps(func)
def secure_func(panel):
if user.get('access_level') == access_level:
return func(panel)
return secure_func
return my_decorator
@user_has_permission('user')
def my_function(panel):
"""
Allows us to retrieve the password for the admin panel.
"""
return f'Password for {panel} panel is 1234.'
print(my_function.__name__)
print(my_function('movies'))
@Devanther: Das `functools.wraps()` kannst Du aus der Betrachtung auch erst einmal heraus lassen, weil das erst einmal keinen direkten Einfluss auf die Funktion des Code hat, sondern ”nur” wenn man „introspection“ der dekorierten Funktion betreibt. Also letztlich betrifft es den Code dann doch, aber der Unterschied den man dann sehen kann, der ist dann hoffentlich zusammen mit der Dokumentation von `functools.wraps()` erhellend.
Re: Decorators with parameters in Python
Verfasst: Dienstag 14. April 2020, 18:02
von nezzcarth
Dekoratoren müssen Callables sein. Daher kann man Dekoratoren neben der Variante mit Funktionen/Closures auch über Klassen definieren, die die __call__ Methode implementieren. Aus dem Beispiel wird dann:
Code: Alles auswählen
# Die Python Konvention, für die Schreibweise von Klassen und Funktionennamen wird hier etwas schwierig
class UserHasPermission:
def __init__(self, access_level):
self.access_level = access_level
def __call__(self, func):
def inner(panel):
if user.get('access_level') == self.access_level:
return func(panel)
return inner
Dadurch spart man (optisch) eine Verschachtelungsebene (bzw. verschiebt sie sich in __init__). Bei Dekoratoren mit Argumenten finde ich diese Variante leichter zu lesen und zu verstehen. Wichtig ist bei beiden Varianten, dass man sich versucht zu verbildlichen, wie die Aufrufreihefolge ist, um zu verstehen, welcher Parameter in welcher Signatur stehen muss. Wenn das Konzept von Dekoratoren für dich insgesamt neu ist, ist es vielleicht einfacher, zunächst mit Dekoratoren ohne Argumente zu beginnen. Da braucht man eine "Ebene" weniger.
Re: Decorators with parameters in Python
Verfasst: Dienstag 14. April 2020, 19:04
von __blackjack__
@nezzcarth: Da musst Du dann noch das `functools.wraps()` unterbringen, wenn die Signatur und Dokumentation erhalten bleiben sollen.
Re: Decorators with parameters in Python
Verfasst: Mittwoch 15. April 2020, 12:25
von nezzcarth
@__blackjack__:
Code: Alles auswählen
...
def __call__(self, func):
@functools.wraps(func)
def inner(panel):
if user.get('access_level') == self.access_level:
return func(panel)
return inner
@UserHasPermission('user')
def my_function2(panel):
...
In [5]: ?my_function2
Signature: my_function2(panel)
Docstring: Allows us to retrieve the password for the admin panel.
File: ~/<ipython-input-3-452b85bb219b>
Type: function
Besser?

Re: Decorators with parameters in Python
Verfasst: Mittwoch 15. April 2020, 16:30
von __blackjack__
Jup. Wobei ich gestehen muss, das ich das in der Regel auch nur für Programme mache wo ich auch eine Dokumentation zu erstelle, weil da wird das dann wirklich wichtig wenn man Teile dafür aus dem Quelltext/Docstrings herausziehen lässt.
Wobei nur besser, aber noch nicht perfekt. Um näher an perfekt zu kommen gibt es das externe `decorator`-Modul.

Re: Decorators with parameters in Python
Verfasst: Mittwoch 15. April 2020, 16:41
von __deets__
Es gibt auch manchmal 3rd-party-Libs, die das wollen, weil die eine Signatur inspizieren, und dann auf die Fresse fallen, wenn die generisch ist.