decorated functions

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
JohnSnock
User
Beiträge: 15
Registriert: Mittwoch 11. August 2021, 19:44

Hi,
ich möchte einige Funktionen schreiben, die alle auf eine Excel Datei zugreifen, die gelesenen Daten verarbeiten und irgendwas zurück geben. Ich möchte nicht in jeder Funktion die gleichen Zeilen von wegen <Excel Datei öffnen> stuff <Excel Datei schließen> schreiben, also dachte ich mir das wäre die richtige Gelegenheit für einen Decorator:

Code: Alles auswählen

def excel_decorator(func):
    def wrapper(*args, **kwargs):
        wb = load_workbook(EXCEL_FILE)
        ws = wb["sheet"]

        func(*args, ws=ws)
        return func(*args, ws=ws)

        wb.close()
    return wrapper


@excel_decorator
def get_value(article, ws=()):
    for row in  ws.iter_rows()
        ...
        return "x"
Bei der Deklaration von get_value habe ich ws=() als Parameter, denn auf ws wird innerhalb der Funktion zugegriffen.
ws wird allerdings im Decorator definiert und von da an die Funktion übergeben.

Da ich viele ähnliche Funktionen in diesem Sinne schreiben werde, frage ich mich, ob es eine Lösung hierfür gibt, ohne dass ich ws=() in jeder neuen Funktion angebe?
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@JohnSnock: Das klingt eher nach einem Einsatzzweck für eine Klasse oder einen Kontextmanager.

Edit: Oder beides, denn eine eigene Klasse, welche die Exceldatei kapselt, würde auch davon profitieren wenn sie ein Kontextmanager ist, um am Ende die gekapselte Ressource wieder abzuräumen/zu schliessen.

Und so wie es da im Moment aussieht ist es reichlich magisch das es da eine global festgelegte Datei mit einem festen Arbeitsblattnamen gibt. „Explicit is better than implicit“. Das sollte nicht zu unpythonisch werden mit der Magie.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn Du immer die selbe Excel-Tabelle öffnen willst, dann ist das ja wenig sinnvoll, das bei jedem Funktionsaufruf zu machen.
Ich würde ein Klasse schreiben:

Code: Alles auswählen

class ExcelData:
    def __int__(self):
        self.workbook = load_workbook(EXCEL_FILE)
        self.sheet = self.workbook["sheet"]

    def get_value(self, article):
        for row in self.sheet.iter_rows():
            ...
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

@JohnSnok: Ergänzend zu den bereits gegebenen Antworten: Wie wird denn deiner Meinung nach die Zeile wb.close() in deinem Code erreicht?
JohnSnock
User
Beiträge: 15
Registriert: Mittwoch 11. August 2021, 19:44

sparrow hat geschrieben: Mittwoch 5. Oktober 2022, 19:17 @JohnSnok: Ergänzend zu den bereits gegebenen Antworten: Wie wird denn deiner Meinung nach die Zeile wb.close() in deinem Code erreicht?
Ist natürlich Quatsch, da hast du recht. Ich habe es korrigiert.


Das Stichwort Kontext Manager schaut gut aus, werde mich dahingehend einlesen. Danke!
Antworten