Jak tworzyć i używać dekoratorów w Pythonie
Dowiedz się, jak pisać i stosować dekoratory w Pythonie. Opanuj funkcje owijania, modyfikowania zachowania, obsługi argumentów i zachowywania metadanych za pomocą zawijania.
Przegląd
Dekoratory to jedna z najbardziej eleganckich i potężnych funkcji składni Pythona, umożliwiająca modyfikowanie zachowania funkcji lub klasy bez trwałej zmiany jej kodu. Są one szeroko stosowane w zagadnieniach przekrojowych, takich jak rejestrowanie czasów wykonywania, wymuszanie uwierzytelniania użytkowników, buforowanie wyników (zapamiętywanie) i kontrolowanie punktów końcowych API.
W skrócie dekorator to funkcja wyższego rzędu, która przyjmuje inną funkcję jako argument, definiuje zagnieżdżoną funkcję opakowującą, która wprowadza niestandardową logikę i zwraca tę funkcję opakowującą. Python zapewnia przejrzystą, skróconą składnię wykorzystującą symbol `@` do stosowania dekoratorów do funkcji, czyniąc je wizualnie eleganckimi.
Podczas pisania dekoratorów zazwyczaj chcesz, aby funkcja dekorowana obsługiwała dowolną liczbę argumentów pozycyjnych i słów kluczowych. Można to osiągnąć projektując zagnieżdżoną funkcję opakowującą tak, aby akceptowała `*args` i `**kwargs` i przekazywała je do funkcji docelowej. Dodatkowo powinieneś użyć `functools.wraps` w funkcji opakowującej, aby zachować dokumentację i metadane nazwy oryginalnej funkcji.
Dane wyjściowe kodu i wykonania
Ten skrypt demonstruje napisanie dekoratora rejestrowania i zawinięcie funkcji w celu sprawdzenia danych wejściowych, wyjściowych i metadanych.
from functools import wraps
# 1. Defining a decorator
def log_execution(func):
@wraps(func) # Preserves original function metadata
def wrapper(*args, **kwargs):
print(f"[Log] Calling function: {func.__name__} with args: {args}")
result = func(*args, **kwargs)
print(f"[Log] Finished {func.__name__}. Result: {result}")
return result
return wrapper
# 2. Applying the decorator using @ syntax
@log_execution
def add_numbers(a, b):
"""Adds two numbers and returns the sum."""
return a + b
# 3. Invoking the decorated function
sum_result = add_numbers(15, 25)
print("Sum Result:", sum_result)
# Verifying metadata preservation
print("Docstring preserved:", add_numbers.__doc__)[Log] Calling function: add_numbers with args: (15, 25)
[Log] Finished add_numbers. Result: 40
Sum Result: 40
Docstring preserved: Adds two numbers and returns the sum.Wdrażanie krok po kroku
- Zdefiniuj zewnętrzną funkcję dekoratora, która przyjmuje funkcję docelową jako argument.
- Zaimportuj i zastosuj @functools.wraps(func) w zagnieżdżonej funkcji opakowania, aby chronić oryginalne metadane.
- Zaimplementuj wrapper(*args, **kwargs), aby przechwytywać zmienne wejściowe, wstrzykiwać logikę i wywoływać funkcję docelową.
- Zwróć obiekt funkcji opakowania z bloku nagłówka dekoratora.
- Zastosuj dekorator, używając @decorator_name bezpośrednio nad sygnaturą funkcji docelowej.
Często zadawane pytania
Dlaczego @functools.wraps jest niezbędny wewnątrz dekoratorów?
Bez zawinięć dekorowana funkcja traci swoją pierwotną tożsamość (jej atrybuty __name__ i __doc__ są zastępowane atrybutami zagnieżdżonej funkcji opakowującej), co utrudnia debugowanie i introspekcję kodu.
Czy mogę zastosować wiele dekoratorów do jednej funkcji?
Tak! Możesz łączyć dekoratory w łańcuchy, umieszczając wiele @ linii. Python stosuje je od dołu do góry (najpierw wykonywana jest definicja funkcji najbliżej).
Powiązane tematy
Opanuj *args i **kwargs w Pythonie. Dowiedz się, jak pisać elastyczne funkcje z dynamicznymi argumentami pozycyjnymi i kluczowymi, rozpakowywać kolekcje i budować funkcje opakowujące.
Jak korzystać z funkcji Lambda w PythonieDowiedz się, jak używać funkcji lambda w Pythonie. Opanuj anonimowe funkcje, wbudowane wywołania zwrotne i sortowanie danych list za pomocą kluczy lambda.
Polecane zasoby Pythona
Poszerzaj swoją wiedzę dzięki powiązanym interaktywnym samouczkom, ściągawkom i porównaniom kodów.
Wyjaśnienie zmiennych i typów danych w Pythonie
Zrozumienie zmiennych Pythona i podstawowych typów danych (łańcuchy, liczby całkowite, zmiennoprzecinkowe, wartości logiczne). Kompletny przewodnik dla początkujących dotyczący przydzielania pamięci w Pythonie.
Ściągawka dotycząca metod słownika Pythona
Poznaj metody słownikowe Pythona. Kompletny przewodnik dotyczący wstawiania, pobierania, aktualizacji i sprawdzania par klucz-wartość.
Python kontra JavaScript: który język programowania jest najlepszy?
Kompleksowe porównanie Pythona i JavaScript. Poznaj różnice w składni, wydajność, przypadki użycia (backend vs frontend) i przykłady kodowania.