Napsat ručně dekorátor není těžké, ale je to pracné.
Je tam vhodné myslet i na takové věci jako správné předávání pozičních a jmenných argumentů nebo kopírování doc stringu a názvu funkce (kvůli helpu a REPL uživatelům).
Funcy to dělá takto: https://github.com/Suor/funcy/blob/master/funcy/decorators.py
Uvnitř se pak používá standardní functools.wraps: https://docs.python.org/3/library/functools.html#functools.wraps
jj a potom jim ty dekorátory vychází krásně čitelně, jako například ten retry (kterej je z nich nejsložitjěší a přitom pěkně pochopitelnej):
@decorator def retry(call, tries, errors=Exception, timeout=0, filter_errors=None): """Makes decorated function retry up to tries times. Retries only on specified errors. Sleeps timeout or timeout(attempt) seconds between tries.""" errors = _ensure_exceptable(errors) for attempt in range(tries): try: return call() except errors as e: if not (filter_errors is None or filter_errors(e)): raise # Reraise error on last attempt if attempt + 1 == tries: raise else: timeout_value = timeout(attempt) if callable(timeout) else timeout if timeout_value > 0: time.sleep(timeout_value)
Nejen kvůli helpu a REPLu, naposledy jsem zjistil, že mi v dekorátoru chybí wraps až ve chvíli, kdy mi sphinx tvrdil, že metoda má signaturu (*args, **kwargs) -> Any. Taková dokumentace je pak na ho-dně pečlivé zvážení, jestli jí vůbec dělat nebo ne.
V tomhle se mi funcy opravdu líbí, všechno to chodí už od výroby. Totéž silent. Odchytává Exception, zatímco "prázdný" except: vlastně znamená except BaseException. Co z toho budeme potřebovat častěji, námořníku? Kávu, nebo to sádlo?
Šlo by něco udělat s tím automatickým nahrazováním "foo_1.py" za spodní index?
4. 10. 2023, 20:12 editováno autorem komentáře