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.
Decorators with parameters in Python
Die Dekorator-Syntax ist syntaktischer Zucker fuer das hier:
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 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)
- 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")
- __blackjack__
- User
- Beiträge: 14032
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
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:
@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.
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'))
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
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:
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.
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
- __blackjack__
- User
- Beiträge: 14032
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@nezzcarth: Da musst Du dann noch das `functools.wraps()` unterbringen, wenn die Signatur und Dokumentation erhalten bleiben sollen.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
@__blackjack__:
Besser? 
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

- __blackjack__
- User
- Beiträge: 14032
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
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.
Wobei nur besser, aber noch nicht perfekt. Um näher an perfekt zu kommen gibt es das externe `decorator`-Modul.
Zuletzt geändert von __blackjack__ am Mittwoch 15. April 2020, 16:51, insgesamt 1-mal geändert.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.