Mari kita mulai dengan dekorator Python.
Dekorator Python adalah fungsi yang membantu menambahkan beberapa fungsi tambahan ke fungsi yang sudah didefinisikan.
Dalam Python, semuanya adalah objek. Fungsi dalam Python adalah objek kelas satu yang berarti bahwa mereka dapat direferensikan oleh variabel, ditambahkan dalam daftar, diteruskan sebagai argumen ke fungsi lain, dll.
Pertimbangkan potongan kode berikut.
def decorator_func(fun):
def wrapper_func():
print("Wrapper function started")
fun()
print("Given function decorated")
# Wrapper function add something to the passed function and decorator
# returns the wrapper function
return wrapper_func
def say_bye():
print("bye!!")
say_bye = decorator_func(say_bye)
say_bye()
# Output:
# Wrapper function started
# bye
# Given function decorated
Di sini, kita dapat mengatakan bahwa fungsi dekorator memodifikasi fungsi say_hello kita dan menambahkan beberapa baris kode tambahan di dalamnya.
Sintaksis python untuk dekorator
def decorator_func(fun):
def wrapper_func():
print("Wrapper function started")
fun()
print("Given function decorated")
# Wrapper function add something to the passed function and decorator
# returns the wrapper function
return wrapper_func
@decorator_func
def say_bye():
print("bye!!")
say_bye()
Mari kita simpulkan semuanya dari pada dengan skenario kasus, tapi sebelum itu mari kita bicara tentang beberapa oop yang berpartisipasi.
Getters dan setter digunakan dalam banyak bahasa pemrograman berorientasi objek untuk memastikan prinsip enkapsulasi data (dipandang sebagai bundling data dengan metode yang beroperasi pada data ini.)
Metode-metode ini tentu saja pengambil untuk mengambil data dan setter untuk mengubah data.
Menurut prinsip ini, atribut kelas dibuat pribadi untuk menyembunyikan dan melindunginya dari kode lain.
Yup, @property pada dasarnya adalah cara pythonic untuk menggunakan getter dan setter.
Python memiliki konsep hebat yang disebut properti yang membuat kehidupan seorang programmer berorientasi objek jauh lebih sederhana.
Mari kita asumsikan bahwa Anda memutuskan untuk membuat kelas yang dapat menyimpan suhu dalam derajat Celcius.
class Celsius:
def __init__(self, temperature = 0):
self.set_temperature(temperature)
def to_fahrenheit(self):
return (self.get_temperature() * 1.8) + 32
def get_temperature(self):
return self._temperature
def set_temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
self._temperature = value
Kode Refactored, Inilah cara kami dapat mencapainya dengan properti.
Dalam Python, properti () adalah fungsi bawaan yang membuat dan mengembalikan objek properti.
Objek properti memiliki tiga metode, pengambil (), setter (), dan hapus ().
class Celsius:
def __init__(self, temperature = 0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
def get_temperature(self):
print("Getting value")
return self.temperature
def set_temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self.temperature = value
temperature = property(get_temperature,set_temperature)
Sini,
temperature = property(get_temperature,set_temperature)
bisa dipecah sebagai,
# make empty property
temperature = property()
# assign fget
temperature = temperature.getter(get_temperature)
# assign fset
temperature = temperature.setter(set_temperature)
Catatan:
- get_temperature tetap menjadi properti alih-alih metode.
Sekarang Anda dapat mengakses nilai suhu dengan menulis.
C = Celsius()
C.temperature
# instead of writing C.get_temperature()
Kita dapat melanjutkan dan tidak mendefinisikan nama get_temperature dan set_temperature karena mereka tidak perlu dan mencemari namespace kelas.
Cara pythonic untuk mengatasi masalah di atas adalah dengan menggunakan @ properti .
class Celsius:
def __init__(self, temperature = 0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
@property
def temperature(self):
print("Getting value")
return self.temperature
@temperature.setter
def temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self.temperature = value
Poin yang Perlu Dicatat -
- Metode yang digunakan untuk mendapatkan nilai didekorasi dengan "@ properti".
- Metode yang berfungsi sebagai setter didekorasi dengan "@ temperature.setter", Jika fungsi itu disebut "x", kita harus menghiasnya dengan "@ x.setter".
- Kami menulis "dua" metode dengan nama yang sama dan jumlah parameter yang berbeda "suhu def (self)" dan "suhu def (self, x)".
Seperti yang Anda lihat, kode ini jelas kurang elegan.
Sekarang, mari kita bicara tentang satu scenerio praktis kehidupan nyata.
Katakanlah Anda telah merancang kelas sebagai berikut:
class OurClass:
def __init__(self, a):
self.x = a
y = OurClass(10)
print(y.x)
Sekarang, mari kita asumsikan bahwa kelas kita menjadi populer di kalangan klien dan mereka mulai menggunakannya dalam program mereka, mereka melakukan semua jenis tugas pada objek.
Dan Suatu hari yang menentukan, klien tepercaya datang kepada kami dan menyarankan bahwa "x" harus bernilai antara 0 dan 1000, ini benar-benar skenario yang mengerikan!
Karena properti itu mudah: Kami membuat versi properti "x".
class OurClass:
def __init__(self,x):
self.x = x
@property
def x(self):
return self.__x
@x.setter
def x(self, x):
if x < 0:
self.__x = 0
elif x > 1000:
self.__x = 1000
else:
self.__x = x
Ini bagus, bukan: Anda bisa mulai dengan implementasi paling sederhana yang bisa dibayangkan, dan Anda bebas untuk bermigrasi ke versi properti tanpa harus mengubah antarmuka! Jadi properti bukan hanya pengganti untuk pengambil dan penyetel!
Anda dapat memeriksa Implementasi ini di sini