Dekoratører i Python
Denne artikkelen forklarer dekoratører i Python.
YouTube Video
Dekoratører i Python
Python-dekoratører er en kraftig funksjon brukt for å legge til ekstra funksjonalitet til funksjoner eller metoder. Dekoratører lar deg legge til ny funksjonalitet uten å endre eksisterende kode, og forbedrer dermed gjenbruk og vedlikeholdsevnen av koden.
Grunnleggende om dekoratører
Python-dekoratører fungerer ved å ta en funksjon som et argument og returnere en ny funksjon med ekstra funksjonalitet. Ved å bruke dekoratører kan du enkelt legge til forbehandling eller etterbehandling til funksjoner.
Uten dekoratører krever endring av en funksjons oppførsel at du redigerer funksjonen direkte. Med dekoratører kan du utvide funksjonalitet uten å endre den opprinnelige implementeringen.
Grunnstrukturen til en dekoratør
1def my_decorator(func):
2 def wrapper():
3 print("Before the function call")
4 func()
5 print("After the function call")
6 return wrapper
7
8@my_decorator
9def say_hello():
10 print("Hello!")
11
12say_hello()
I dette eksempelet fungerer my_decorator
-funksjonen som en dekoratør og omgir say_hello
-funksjonen. Dekoratøren brukes ved hjelp av @my_decorator
-syntaksen, og når say_hello()
kalles, utføres forhånds- og etterbehandlingen som dekoratøren gir automatisk.
Hvordan dekoratører fungerer
Dekoratorer fungerer gjennom følgende steg.
-
Dekoratøren tar en funksjon (eller metode) som et argument.
-
Den definerer en innpakningsfunksjon for å kjøre den opprinnelige funksjonen.
-
Innpakningsfunksjonen utfører ekstra prosessering før eller etter at den opprinnelige funksjonen er kjørt.
-
Dekoratøren returnerer innpakningsfunksjonen. Som et resultat blir den opprinnelige funksjonen erstattet med en ny, dekorert funksjon.
Dekoratører for funksjoner med argumenter
Når du bruker en dekoratør på en funksjon med argumenter, må innpakningsfunksjonen justeres for å akseptere disse argumentene.
1def my_decorator(func):
2 def wrapper(*args, **kwargs):
3 print("Before the function call")
4 result = func(*args, **kwargs)
5 print("After the function call")
6 return result
7 return wrapper
8
9@my_decorator
10def greet(name):
11 print(f"Hello, {name}!")
12
13greet("Alice")
Ved å bruke *args
og **kwargs
er det mulig å håndtere funksjoner som aksepterer et vilkårlig antall argumenter og nøkkelordargumenter. Dette tillater at dekoratører kan brukes generisk på funksjoner med enhver type argumenter.
Eksempler på bruk av dekoratorer
Dekorator for logging
Dekoratorer brukes ofte for å legge til loggefunksjonalitet. For eksempel, ved å lage en dekorator som logger før og etter utførelsen av en funksjon, kan du registrere når funksjonen blir kalt og hvor lang tid det tar å utføre den.
1import time
2
3def log_time(func):
4 def wrapper(*args, **kwargs):
5 start_time = time.time()
6 print(f"Calling function '{func.__name__}'...")
7 result = func(*args, **kwargs)
8 end_time = time.time()
9 print(f"Function '{func.__name__}' completed in {end_time - start_time} seconds")
10 return result
11 return wrapper
12
13@log_time
14def long_task(duration):
15 time.sleep(duration)
16 print("Task completed!")
17
18long_task(2)
I dette eksempelet måler log_time
-dekoratoren kjøretiden til en funksjon og skriver den ut som en logg. long_task
-funksjonen er pakket inn i dekoratoren, og dens kjøretid blir registrert under kjøring.
Dekorator for rettighetsstyring
Dekoratorer kan også brukes for rettighetsstyring. For eksempel kan du begrense behandling ved å sjekke om en bruker har spesifikke rettigheter.
1def requires_permission(user_role):
2 def decorator(func):
3 def wrapper(*args, **kwargs):
4 if user_role != "admin":
5 print("Permission denied!")
6 return
7 return func(*args, **kwargs)
8 return wrapper
9 return decorator
10
11@requires_permission("admin")
12def delete_user(user_id):
13 print(f"User {user_id} has been deleted.")
14
15delete_user(123) # Executed
16delete_user = requires_permission("guest")(delete_user)
17delete_user(456) # Permission denied!
requires_permission
-dekoratoren begrenser utførelsen av en funksjon basert på en brukers rolle. Ved å konsolidere slik logikk i en dekorator kan du forhindre at rettighetslogikk spres over hele koden din, noe som forbedrer lesbarheten.
Nesting av dekoratorer
Det er mulig å bruke flere dekoratorer. Når flere dekoratorer brukes på en enkelt funksjon, kjøres de i rekkefølge fra topp til bunn.
1def uppercase(func):
2 def wrapper(*args, **kwargs):
3 result = func(*args, **kwargs)
4 return result.upper()
5 return wrapper
6
7def exclaim(func):
8 def wrapper(*args, **kwargs):
9 result = func(*args, **kwargs)
10 return result + "!"
11 return wrapper
12
13@uppercase
14@exclaim
15def greet(name):
16 return f"Hello, {name}"
17
18print(greet("Alice")) # "HELLO, ALICE!"
I dette eksempelet brukes to dekoratorer på greet
-funksjonen. @exclaim
-dekoratoren legger til et utropstegn på slutten av strengen, og deretter konverterer @uppercase
strengen til store bokstaver.
Dekoratorer for klassemåter
Dekoratorer kan også brukes med klassemåter. Dette er spesielt nyttig når du vil kontrollere oppførselen til metoder i en klasse. Når du bruker dekoratorer på klassemåter, må du være oppmerksom på argumenter som self
eller cls
.
1def log_method_call(func):
2 def wrapper(self, *args, **kwargs):
3 print(f"Calling method '{func.__name__}'...")
4 return func(self, *args, **kwargs)
5 return wrapper
6
7class MyClass:
8 @log_method_call
9 def greet(self, name):
10 print(f"Hello, {name}")
11
12obj = MyClass()
13obj.greet("Bob")
I dette eksempelet brukes log_method_call
-dekoratoren på greet
-metoden for å skrive ut en logg når metoden kalles.
Forsiktighetsregler med dekoratorer
Det finnes noen hensyn når man bruker dekoratorer. Dekoratorer kan potensielt endre det opprinnelige navnet og dokumentasjonsstrengen til en funksjon (f.eks. __name__
eller __doc__
), så det anbefales å bruke functools.wraps
for å bevare denne informasjonen.
1import functools
2
3def my_decorator(func):
4 @functools.wraps(func)
5 def wrapper(*args, **kwargs):
6 print("Before the function call")
7 return func(*args, **kwargs)
8 return wrapper
Ved å bruke @functools.wraps
sikrer du at metadataene til den opprinnelige funksjonen blir korrekt overført til innpakningsfunksjonen.
Sammendrag
Python-dekoratorer er et svært kraftig verktøy som lar deg kortfattet legge til ekstra funksjonalitet til funksjoner og metoder. De kan brukes i ulike scenarier for å redusere kode-duplisering og forbedre vedlikeholdbarhet og gjenbrukbarhet. Ved å forstå hvordan dekoratorer fungerer, kan du skrive mer effektiv og fleksibel kode.
Du kan følge med på artikkelen ovenfor ved å bruke Visual Studio Code på vår YouTube-kanal. Vennligst sjekk ut YouTube-kanalen.