Mga Decorator sa Python

Mga Decorator sa Python

Ipinaliwanag ng artikulong ito ang tungkol sa mga decorator sa Python.

YouTube Video

Mga Decorator sa Python

Ang mga decorator sa Python ay isang makapangyarihang tampok na ginagamit upang magdagdag ng karagdagang pag-andar sa mga function o pamamaraan. Ang mga decorator ay nagbibigay-daan sa iyo na magdagdag ng bagong pag-andar nang hindi binabago ang umiiral na code, sa gayon ay pinapahusay ang reusability at pagpapanatili ng code.

Mga Pangunahing Kaalaman sa Decorators

Ang mga decorator sa Python ay gumagana sa pamamagitan ng pagkuha ng isang function bilang argumento at pagbabalik ng bagong function na may idinagdag na pag-andar. Sa pamamagitan ng paggamit ng mga decorator, madali kang makakapagdagdag ng pre-processing o post-processing sa mga function.

Kung walang mga decorator, ang pagbabago ng asal ng isang function ay nangangailangan ng direktang pag-edit sa mismong function. Sa mga decorator, maaari mong palawigin ang pag-andar nang hindi binabago ang orihinal na implementasyon.

Pangunahing Estruktura ng isang Decorator

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

Sa halimbawang ito, ang function na my_decorator ay nagsisilbing isang decorator, na bumabalot sa function na say_hello. Ang decorator ay inilalapat gamit ang syntax na @my_decorator, at kapag tinawag ang say_hello(), ang pre- at post-processing na ibinibigay ng decorator ay awtomatikong isinasagawa.

Paano Gumagana ang Mga Decorator

Gumagana ang mga decorator sa sumusunod na mga hakbang.

  1. Ang decorator ay kumukuha ng isang function (o pamamaraan) bilang isang argumento.

  2. Ito ay nagtatakda ng isang wrapper function upang isagawa ang orihinal na function.

  3. Ang wrapper function ay gumagawa ng karagdagang pagpoproseso bago o pagkatapos isagawa ang orihinal na function.

  4. Ang decorator ay nagbabalik ng wrapper function. Bilang resulta, ang orihinal na function ay napapalitan ng bago, na may dekorasyong function.

Mga Decorator para sa mga Function na may mga Argumento

Kapag gumagamit ng decorator sa isang function na may mga argumento, kailangang i-adjust ang wrapper function upang tanggapin ang mga argumentong iyon.

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

Sa paggamit ng *args at **kwargs, posible itong makapagproseso ng mga function na tumatanggap ng anumang bilang ng mga argumento at keyword na argumento. Ito ay nagbibigay-daan na mailapat ang mga decorator sa pangkalahatan sa mga function na may anumang uri ng mga argumento.

Mga Halimbawa ng Paglalapat ng Mga Dekorador

Dekorador para sa Pag-log

Karaniwang ginagamit ang mga dekorador upang magdagdag ng pag-log na kakayahan. Halimbawa, sa pamamagitan ng paggawa ng dekorador na naglo-log bago at pagkatapos magpatupad ng isang function, maaari mong i-record kung kailan tinawag ang function at kung gaano katagal ito tumagal para magpatupad.

 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)

Sa halimbawang ito, sinusukat ng dekorador na log_time ang oras ng pagpapatupad ng isang function at inilalabas ito bilang log. Ang function na long_task ay binalot ng dekorador, at ang oras ng pagpapatupad nito ay naitala habang tumatakbo.

Dekorador para sa Pamamahala ng Pahintulot

Magagamit din ang mga dekorador para sa pamamahala ng pahintulot. Halimbawa, maaari mong paghigpitan ang proseso sa pamamagitan ng pagsusuri kung ang isang user ay may mga tiyak na pahintulot.

 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!

Hinahadlangan ng dekorador na requires_permission ang pagpapatupad ng isang function batay sa papel ng isang user. Sa pamamagitan ng pagsasama-sama ng ganitong lohika sa isang dekorador, maiiwasan mong ikalat ang lohika ng pamamahala ng pahintulot sa buong code mo, na nagpapabuti sa nababasa.

Pag-nest ng Mga Dekorador

Posibleng maglapat ng maraming dekorador. Kapag maraming dekorador ang ipinapatong sa isang function, sila ay nagpapatupad mula sa itaas pababa.

 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!"

Sa halimbawang ito, dalawang dekorador ang inilapat sa function na greet. Ang dekorador na @exclaim ay nagdadagdag ng tandang padamdam sa dulo ng string, at ang @uppercase ay nagko-convert ng string sa uppercase.

Mga Dekorador para sa Mga Pamamaraan ng Klase

Magagamit din ang mga dekorador sa mga pamamaraan ng klase. Ito ay lalong kapaki-pakinabang kapag nais mong kontrolin ang gawi ng mga pamamaraan sa loob ng isang klase. Kapag nag-aaplay ng mga dekorador sa mga pamamaraan ng klase, kailangan mong mag-ingat sa mga argumento tulad ng self o 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")

Sa halimbawang ito, ang dekorador na log_method_call ay inilapat sa pamamaraan na greet upang maglabas ng log kapag tinawag ang pamamaraan.

Pag-iingat sa Paggamit ng Mga Dekorador

May ilang pagsasaalang-alang kapag gumagamit ng mga dekorador. Maaaring baguhin ng mga dekorador ang orihinal na pangalan ng function at ang dokumentasyon nito (hal., __name__ o __doc__), kaya't inirerekomenda ang paggamit ng functools.wraps upang mapanatili ang impormasyong ito.

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

Ang paggamit ng @functools.wraps ay tinitiyak na ang metadata ng orihinal na function ay maayos na naipapasa sa pambalot na function.

Buod

Ang mga dekorador sa Python ay isang napakalakas na kasangkapan na nagbibigay-daan sa iyo upang maikling idagdag ang karagdagang mga functionality sa mga function at pamamaraan. Maaari silang magamit sa iba't ibang mga sitwasyon upang mabawasan ang pag-uulit ng code at mapabuti ang kakayahang i-maintain at muling magamit. Sa pamamagitan ng pag-unawa kung paano gumagana ang mga dekorador, makakagawa ka ng mas mahusay at mas nababaluktot na code.

Maaari mong sundan ang artikulo sa itaas gamit ang Visual Studio Code sa aming YouTube channel. Paki-check din ang aming YouTube channel.

YouTube Video