Dekoratører er et veldig kraftig og nyttig verktøy i Python siden det lar programmerere endre oppførselen til en funksjon eller klasse. Dekoratorer lar oss pakke inn en annen funksjon for å utvide funksjonen til den innpakket funksjonen, uten å endre den permanent. Men før du dykker dypt inn i dekoratører, la oss forstå noen konsepter som vil være nyttige når du lærer dekoratørene.
Førsteklasses objekter
I Python er funksjoner førsteklasses objekter som betyr at funksjoner i Python kan brukes eller sendes som argumenter.
Egenskaper til førsteklasses funksjoner:
- En funksjon er en forekomst av objekttypen.
- Du kan lagre funksjonen i en variabel.
- Du kan overføre funksjonen som en parameter til en annen funksjon.
- Du kan returnere funksjonen fra en funksjon.
- Du kan lagre dem i datastrukturer som hashtabeller, lister, ...
Vurder eksemplene nedenfor for bedre forståelse.
Eksempel 1: Behandle funksjonene som objekter.
Python3
# Python program to illustrate functions> # can be treated as objects> def> shout(text):> > return> text.upper()> print> (shout(> 'Hello'> ))> yell> => shout> print> (yell(> 'Hello'> ))> |
>
>
Produksjon:
HELLO HELLO>
I eksemplet ovenfor har vi tilordnet funksjonen shout til en variabel. Dette vil ikke kalle funksjonen i stedet, det tar funksjonsobjektet referert til av et rop og lager et andre navn som peker på det, rop.
Eksempel 2: Sender funksjonen som et argument
Python3
# Python program to illustrate functions> # can be passed as arguments to other functions> def> shout(text):> > return> text.upper()> def> whisper(text):> > return> text.lower()> def> greet(func):> > # storing the function in a variable> > greeting> => func(> '''Hi, I am created by a function passed as an argument.'''> )> > print> (greeting)> greet(shout)> greet(whisper)> |
>
>
Produksjon:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT. hi, i am created by a function passed as an argument.>
I eksemplet ovenfor tar hilsefunksjonen en annen funksjon som parameter (rop og hvisk i dette tilfellet). Funksjonen som sendes som et argument kalles deretter inne i funksjonen hilsen.
Eksempel 3: Returnere funksjoner fra en annen funksjon.
Python3
skriv json til filen python
# Python program to illustrate functions> # Functions can return another function> def> create_adder(x):> > def> adder(y):> > return> x> +> y> > return> adder> add_15> => create_adder(> 15> )> print> (add_15(> 10> ))> |
>
>
Produksjon:
25>
I eksemplet ovenfor har vi laget en funksjon inne i en annen funksjon og deretter returnert funksjonen som er opprettet inne.
De tre eksemplene ovenfor skildrer de viktige konseptene som trengs for å forstå dekoratører. Etter å ha gått gjennom dem, la oss nå dykke dypt inn i dekoratører.
Dekoratører
Som nevnt ovenfor brukes dekoratørene til å endre oppførselen til funksjon eller klasse. I Decorators blir funksjoner tatt som argumentet inn i en annen funksjon og deretter kalt inne i wrapper-funksjonen.
Syntaks for dekoratør:
@gfg_decorator def hello_decorator(): print('Gfg') '''Above code is equivalent to - def hello_decorator(): print('Gfg') hello_decorator = gfg_decorator(hello_decorator)'''>
I koden ovenfor er gfg_decorator en anropbar funksjon, som vil legge til noe kode på toppen av en annen anropbar funksjon, hello_decorator-funksjonen og returnere wrapper-funksjonen.
Dekoratør kan endre oppførsel :
Python3
# defining a decorator> def> hello_decorator(func):> > # inner1 is a Wrapper function in> > # which the argument is called> > > # inner function can access the outer local> > # functions like in this case 'func'> > def> inner1():> > print> (> 'Hello, this is before function execution'> )> > # calling the actual function now> > # inside the wrapper function.> > func()> > print> (> 'This is after function execution'> )> > > return> inner1> # defining a function, to be called inside wrapper> def> function_to_be_used():> > print> (> 'This is inside the function !!'> )> # passing 'function_to_be_used' inside the> # decorator to control its behaviour> function_to_be_used> => hello_decorator(function_to_be_used)> # calling the function> function_to_be_used()> |
>
>
Produksjon:
Hello, this is before function execution This is inside the function !! This is after function execution>
La oss se oppførselen til koden ovenfor og hvordan den kjører trinn for trinn når funksjonen_til_benyttes kalles.
La oss hoppe til et annet eksempel hvor vi enkelt kan finne ut utførelsestiden for en funksjon ved hjelp av en dekoratør.
Python3
# importing libraries> import> time> import> math> # decorator to calculate duration> # taken by any function.> def> calculate_time(func):> > > # added arguments inside the inner1,> > # if function takes any arguments,> > # can be added like this.> > def> inner1(> *> args,> *> *> kwargs):> > # storing time before function execution> > begin> => time.time()> > > func(> *> args,> *> *> kwargs)> > # storing time after function execution> > end> => time.time()> > print> (> 'Total time taken in : '> , func.__name__, end> -> begin)> > return> inner1> # this can be added to any function present,> # in this case to calculate a factorial> @calculate_time> def> factorial(num):> > # sleep 2 seconds because it takes very less time> > # so that you can see the actual difference> > time.sleep(> 2> )> > print> (math.factorial(num))> # calling the function.> factorial(> 10> )> |
>
>
Produksjon:
3628800 Total time taken in : factorial 2.0061802864074707>
Hva om en funksjon returnerer noe eller et argument sendes til funksjonen?
I alle eksemplene ovenfor returnerte ikke funksjonene noe, så det var ikke noe problem, men man kan trenge den returnerte verdien.
Python3
def> hello_decorator(func):> > def> inner1(> *> args,> *> *> kwargs):> > > print> (> 'before Execution'> )> > > # getting the returned value> > returned_value> => func(> *> args,> *> *> kwargs)> > print> (> 'after Execution'> )> > > # returning the value to the original frame> > return> returned_value> > > return> inner1> # adding decorator to the function> @hello_decorator> def> sum_two_numbers(a, b):> > print> (> 'Inside the function'> )> > return> a> +> b> a, b> => 1> ,> 2> # getting the value through return of the function> print> (> 'Sum ='> , sum_two_numbers(a, b))> |
>
>
Produksjon:
before Execution Inside the function after Execution Sum = 3>
I eksemplet ovenfor kan du merke en stor forskjell i parametrene til den indre funksjonen. Den indre funksjonen tar argumentet som *args og **kwargs, noe som betyr at en tuppel med posisjonsargumenter eller en ordbok med nøkkelordargumenter kan sendes av hvilken som helst lengde. Dette gjør den til en generell dekoratør som kan dekorere en funksjon med et hvilket som helst antall argumenter.
Kjededekoratører
I enklere termer betyr å lenke dekoratører å dekorere en funksjon med flere dekoratører.
tuppel java
Eksempel:
Python3
# code for testing decorator chaining> def> decor1(func):> > def> inner():> > x> => func()> > return> x> *> x> > return> inner> def> decor(func):> > def> inner():> > x> => func()> > return> 2> *> x> > return> inner> @decor1> @decor> def> num():> > return> 10> @decor> @decor1> def> num2():> > return> 10> > print> (num())> print> (num2())> |
>
>
Produksjon:
400 200>
Eksemplet ovenfor ligner på å kalle funksjonen som -
decor1(decor(num)) decor(decor1(num2))>