logo

Decorateurs in Python

Decorateurs zijn een zeer krachtig en nuttig hulpmiddel in Python, omdat programmeurs hiermee het gedrag van een functie of klasse kunnen wijzigen. Met decorateurs kunnen we een andere functie inpakken om het gedrag van de ingepakte functie uit te breiden, zonder deze permanent te wijzigen. Maar voordat we diep in de decorateurs duiken, moeten we enkele concepten begrijpen die van pas kunnen komen bij het leren van de decorateurs.

Eersteklas objecten
In Python zijn functies eersteklas voorwerpen wat betekent dat functies in Python kunnen worden gebruikt of doorgegeven als argumenten.
Eigenschappen van eersteklas functies:

  • Een functie is een instantie van het objecttype.
  • U kunt de functie opslaan in een variabele.
  • U kunt de functie als parameter doorgeven aan een andere functie.
  • U kunt de functie uit een functie retourneren.
  • Je kunt ze opslaan in datastructuren zoals hashtabellen, lijsten, …

Bekijk de onderstaande voorbeelden voor een beter begrip.



Voorbeeld 1: De functies behandelen als objecten.

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

>

>

Uitgang:

HELLO HELLO>

In het bovenstaande voorbeeld hebben we de functie shout aan een variabele toegewezen. Hierdoor wordt de functie niet aangeroepen, maar wordt het functieobject waarnaar wordt verwezen door een schreeuw genomen en wordt een tweede naam gemaakt die ernaar verwijst, schreeuw.

Voorbeeld 2: De functie doorgeven als 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)>

>

>

Uitgang:

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

In het bovenstaande voorbeeld neemt de begroetingsfunctie een andere functie als parameter (in dit geval schreeuwen en fluisteren). De functie die als argument wordt doorgegeven, wordt vervolgens binnen de functie greet aangeroepen.

Voorbeeld 3: Functies retourneren uit een andere functie.

Python3




probeer catch catch java
# 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>))>

>

>

Uitgang:

25>

In het bovenstaande voorbeeld hebben we een functie binnen een andere functie gemaakt en vervolgens de functie teruggegeven die daarbinnen is gemaakt.
De bovenstaande drie voorbeelden geven de belangrijke concepten weer die nodig zijn om decorateurs te begrijpen. Laten we, nadat we ze hebben doorgenomen, nu diep in de decorateurs duiken.

Decorateurs

Zoals hierboven vermeld, worden de decorateurs gebruikt om het gedrag van functie of klasse te wijzigen. In Decorators worden functies als argument in een andere functie opgenomen en vervolgens binnen de wrapperfunctie aangeroepen.

Syntaxis voor decorateur:

@gfg_decorator def hello_decorator(): print('Gfg') '''Above code is equivalent to - def hello_decorator(): print('Gfg') hello_decorator = gfg_decorator(hello_decorator)'''>

In de bovenstaande code is gfg_decorator een opvraagbare functie, die wat code toevoegt aan een andere opvraagbare functie, de functie hello_decorator, en de wrapper-functie retourneert.

Decorateur kan de gedrag :

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

>

>

Uitgang:

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

Laten we het gedrag van de bovenstaande code bekijken en stap voor stap bekijken hoe deze wordt uitgevoerd wanneer de function_to_be_used wordt aangeroepen.

Laten we naar een ander voorbeeld gaan waar we er gemakkelijk achter kunnen komen de uitvoeringstijd van een functie met behulp van een decorateur.

Python3

map hernoemen in linux




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

>

>

Uitgang:

3628800 Total time taken in : factorial 2.0061802864074707>

Wat gebeurt er als een functie iets retourneert of als er een argument aan de functie wordt doorgegeven?

In alle bovenstaande voorbeelden hebben de functies niets geretourneerd, dus er was geen probleem, maar mogelijk heeft u de geretourneerde waarde nodig.

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

>

>

Uitgang:

before Execution Inside the function after Execution Sum = 3>

In het bovenstaande voorbeeld merkt u mogelijk een groot verschil in de parameters van de innerlijke functie. De innerlijke functie neemt het argument als *args en **kwargs, wat betekent dat een tupel positionele argumenten of een woordenboek met trefwoordargumenten van elke lengte kan worden doorgegeven. Dit maakt het tot een algemene decorateur die een functie met een willekeurig aantal argumenten kan versieren.

Decorateurs ketenen

In eenvoudiger bewoordingen betekent het aan elkaar koppelen van decorateurs het decoreren van een functie met meerdere decorateurs.

Voorbeeld:

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

>

>

Uitgang:

400 200>

Het bovenstaande voorbeeld is vergelijkbaar met het aanroepen van de functie als –

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