Seite 1 von 1

decorated functions

Verfasst: Mittwoch 5. Oktober 2022, 13:29
von JohnSnock
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?

Re: decorated functions

Verfasst: Mittwoch 5. Oktober 2022, 17:55
von __blackjack__
@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.

Re: decorated functions

Verfasst: Mittwoch 5. Oktober 2022, 19:10
von Sirius3
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():
            ...

Re: decorated functions

Verfasst: Mittwoch 5. Oktober 2022, 19:17
von sparrow
@JohnSnok: Ergänzend zu den bereits gegebenen Antworten: Wie wird denn deiner Meinung nach die Zeile wb.close() in deinem Code erreicht?

Re: decorated functions

Verfasst: Freitag 7. Oktober 2022, 18:00
von JohnSnock
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!