logo

Dekoratörer i Python

Dekoratörer är ett mycket kraftfullt och användbart verktyg i Python eftersom det tillåter programmerare att ändra beteendet hos en funktion eller klass. Dekoratörer tillåter oss att slå in en annan funktion för att förlänga beteendet hos den inslagna funktionen, utan att permanent ändra den. Men innan vi dyker djupt in i dekoratörer, låt oss förstå några begrepp som kommer att vara användbara när vi lär oss dekoratörerna.

Första klass objekt
I Python är funktioner förstklassiga objekt vilket innebär att funktioner i Python kan användas eller skickas som argument.
Egenskaper för förstklassiga funktioner:

  • En funktion är en instans av objekttypen.
  • Du kan lagra funktionen i en variabel.
  • Du kan skicka funktionen som en parameter till en annan funktion.
  • Du kan returnera funktionen från en funktion.
  • Du kan lagra dem i datastrukturer som hashtabeller, listor, ...

Betrakta exemplen nedan för bättre förståelse.



Exempel 1: Behandla funktionerna som objekt.

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'>))>

>

>

Produktion:

HELLO HELLO>

I exemplet ovan har vi tilldelat funktionen shout till en variabel. Detta kommer inte att anropa funktionen istället, det tar funktionsobjektet som refereras till av ett rop och skapar ett andra namn som pekar på det, yell.

Exempel 2: Skickar funktionen som ett 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)>

>

>

Produktion:

HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT. hi, i am created by a function passed as an argument.>

I exemplet ovan tar hälsningsfunktionen en annan funktion som parameter (ropa och viska i detta fall). Funktionen som skickas som ett argument anropas sedan inuti funktionen greet.

Exempel 3: Returnera funktioner från en annan funktion.

Python3




1 av 1000
# 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>))>

>

>

Produktion:

25>

I exemplet ovan har vi skapat en funktion inuti en annan funktion och sedan returnerat funktionen som skapats inuti.
Ovanstående tre exempel skildrar de viktiga begrepp som behövs för att förstå dekoratörer. Efter att ha gått igenom dem låt oss nu dyka djupt in i dekoratörer.

Dekoratörer

Som nämnts ovan används dekoratörerna för att ändra beteendet hos funktion eller klass. I Decorators tas funktioner som argument till en annan funktion och anropas sedan inuti omslagsfunktionen.

Syntax för 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 ovanstående kod är gfg_decorator en anropsbar funktion, som kommer att lägga till lite kod ovanpå någon annan anropsbar funktion, hello_decorator funktion och returnera omslagsfunktionen.

Dekoratör kan ändra beteende :

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()>

>

>

Produktion:

Hello, this is before function execution This is inside the function !! This is after function execution>

Låt oss se beteendet hos ovanstående kod och hur den körs steg för steg när function_to_beused anropas.

Låt oss hoppa till ett annat exempel där vi enkelt kan ta reda på det exekveringstiden för en funktion med hjälp 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>)>

>

>

Produktion:

3628800 Total time taken in : factorial 2.0061802864074707>

Vad händer om en funktion returnerar något eller ett argument skickas till funktionen?

I alla ovanstående exempel returnerade funktionerna ingenting så det var inget problem, men man kan behöva det returnerade värdet.

Python3

js base64 avkoda




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))>

>

>

Produktion:

before Execution Inside the function after Execution Sum = 3>

I exemplet ovan kanske du märker en stor skillnad i parametrarna för den inre funktionen. Den inre funktionen tar argumentet som *args och **kwargs, vilket innebär att en tuppel av positionsargument eller en ordbok med nyckelordsargument kan skickas av valfri längd. Detta gör den till en allmän dekoratör som kan dekorera en funktion med hur många argument som helst.

Kedjedekoratörer

I enklare termer betyder att kedja dekoratörer att dekorera en funktion med flera dekoratörer.

Exempel:

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())>

>

>

Produktion:

400 200>

Exemplet ovan liknar att anropa funktionen som –

decor1(decor(num)) decor(decor1(num2))>