Python dekoratörleri ile başlayalım.
Python dekoratörü, önceden tanımlanmış bir işleve bazı ek işlevler eklemeye yardımcı olan bir işlevdir.
Python'da her şey bir nesnedir. Python'daki işlevler birinci sınıf nesnelerdir, yani listelere eklenen, başka bir işleve argüman olarak iletilen bir değişken tarafından başvurulabilir.
Aşağıdaki kod snippet'ini düşünün.
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
Burada, dekoratör işlevinin say_hello işlevimizi değiştirdiğini ve içine bazı ekstra kod satırları eklediğini söyleyebiliriz.
Dekoratör için Python sözdizimi
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()
Her şeyi bir senaryodan ziyade sonuçlandıralım, ama bundan önce bazı ayıp prensipleri hakkında konuşalım.
Harfler ve ayarlayıcılar, veri kapsülleme ilkesini sağlamak için birçok nesne yönelimli programlama dilinde kullanılır (verilerin bu veriler üzerinde çalışan yöntemlerle birleştirilmesi olarak görülür).
Bu yöntemler elbette verileri almak için alıcı ve verileri değiştirmek için ayarlayıcıdır.
Bu ilkeye göre, bir sınıfın nitelikleri, onları diğer kodlardan gizlemek ve korumak için özel yapılır.
Evet, @property temel olarak alıcıları ve ayarlayıcıları kullanmanın pythonic bir yoludur.
Python, nesneye yönelik bir programlayıcının hayatını çok daha basit hale getiren özellik adı verilen harika bir konsepte sahiptir.
Sıcaklığı Celsius derecesinde depolayabilecek bir sınıf yapmaya karar verdiğinizi varsayalım.
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
Refactored Code, İşte bunu mülkle nasıl başarabiliriz.
Python'da property (), bir özellik nesnesi oluşturan ve döndüren yerleşik bir işlevdir.
Bir özellik nesnesinin getter (), setter () ve delete () olmak üzere üç yöntemi vardır.
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)
Buraya,
temperature = property(get_temperature,set_temperature)
olarak parçalanmış olabilir,
# make empty property
temperature = property()
# assign fget
temperature = temperature.getter(get_temperature)
# assign fset
temperature = temperature.setter(set_temperature)
Dikkat Edilmesi Gereken Noktalar:
- get_temperature yöntem yerine bir özellik olarak kalır.
Artık sıcaklığın değerine yazarak erişebilirsiniz.
C = Celsius()
C.temperature
# instead of writing C.get_temperature()
Daha da devam edebilir ve get_temperature ve set_temperature adlarını gereksiz olduklarından tanımlayabilir ve sınıf ad alanını kirletebiliriz.
Pythonic yolu yukarıdaki sorunla başa çıkmak için kullanmaktır @property .
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
Dikkat Edilmesi Gereken Noktalar -
- Bir değer elde etmek için kullanılan bir yöntem "@property" ile süslenmiştir.
- Ayarlayıcı olarak işlev görmesi gereken yöntem "@ temperature.setter" ile dekore edilmiştir. Eğer fonksiyon "x" olarak adlandırılmış olsaydı, bunu "@ x.setter" ile süslememiz gerekirdi.
- Aynı ada ve farklı sayıda "def temperature (self)" ve "def temperature (self, x)" parametrelerine sahip "iki" yöntem yazdık.
Gördüğünüz gibi, kod kesinlikle daha az zarif.
Şimdi, gerçek bir pratik senaryo hakkında konuşalım.
Diyelim ki aşağıdaki gibi bir sınıf tasarladınız:
class OurClass:
def __init__(self, a):
self.x = a
y = OurClass(10)
print(y.x)
Şimdi, sınıfımızın müşteriler arasında popüler olduğunu ve programlarında kullanmaya başladığını varsayalım, nesneye her türlü görevi yaptılar.
Ve bir kader gün, güvenilir bir müşteri bize geldi ve "x" değerinin 0 ile 1000 arasında bir değer olması gerektiğini önerdi, bu gerçekten korkunç bir senaryo!
Özellikleri nedeniyle kolaydır: "x" özellik sürümünü oluştururuz.
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
Bu harika, değil mi: Akla gelebilecek en basit uygulama ile başlayabilirsiniz ve daha sonra arayüzü değiştirmek zorunda kalmadan bir mülk sürümüne geçiş yapmakta özgürsünüz! Yani özellikler sadece alıcılar ve ayarlayıcıların yerini almaz!
Bu Uygulamayı buradan kontrol edebilirsiniz