Yanıtlar:
Özellikler özel bir niteliktir. Temel olarak, Python aşağıdaki kodla karşılaştığında:
spam = SomeObject()
print(spam.eggs)
yukarıyı eggsiçinde spamve sonra inceler eggsbir olup olmadığını görmek için __get__, __set__ya da __delete__yöntemi - eğer olursa, bu bir özelliktir. O takdirde ise bir özellik yerine sadece döndükten sonra eggsnesneyi çağıracağı (başka herhangi bir özelliğe için olduğu gibi) __get__yöntem ve getiri ne olursa olsun bu yöntem döndürür (biz arama yaptıklarını beri).
Python'un veri modeli ve tanımlayıcıları hakkında daha fazla bilgi .
Bir özellik ile, bir özellik ile (uyarılar kullanmıyorsanız) sahip olmadığınız alıcı, ayarlayıcı ve silme yöntemleri üzerinde tam kontrole sahip olursunuz.
class A(object):
_x = 0
'''A._x is an attribute'''
@property
def x(self):
'''
A.x is a property
This is the getter method
'''
return self._x
@x.setter
def x(self, value):
"""
This is the setter method
where I can check it's not assigned a value < 0
"""
if value < 0:
raise ValueError("Must be >= 0")
self._x = value
>>> a = A()
>>> a._x = -1
>>> a.x = -1
Traceback (most recent call last):
File "ex.py", line 15, in <module>
a.x = -1
File "ex.py", line 9, in x
raise ValueError("Must be >= 0")
ValueError: Must be >= 0
x. Tek yön. Sınıfın kullanıcısı _x hakkında bilgi bulursa, riski kendi sorumluluğunda kullanır.
Genel olarak konuşursak, bir özellik ve nitelik aynı şeydir. Bununla birlikte, Python'da bir özniteliğe (veya diğer verilere) alıcı / ayarlayıcı erişimi sağlayan bir özellik dekoratörü vardır.
class MyObject(object):
# This is a normal attribute
foo = 1
@property
def bar(self):
return self.foo
@bar.setter
def bar(self, value):
self.foo = value
obj = MyObject()
assert obj.foo == 1
assert obj.bar == obj.foo
obj.bar = 2
assert obj.foo == 2
assert obj.bar == obj.foo
Özellik, normal nitelikler gibi değerler almanıza ve ayarlamanıza izin verir, ancak altında sizin için bir alıcıya ve ayarlayıcıya çeviri olarak adlandırılan bir yöntem vardır. Arayanların ve ayarlayıcıların ortak plakasını kesmek gerçekten kolaylık.
Diyelim ki, ihtiyacınız olan bir şey için bazı x ve y koordinatlarına sahip bir sınıfınız var. Bunları ayarlamak için aşağıdaki gibi bir şey yapmak isteyebilirsiniz:
myObj.x = 5
myObj.y = 10
Bakmak ve düşünmek yazmaktan çok daha kolay:
myObj.setX(5)
myObj.setY(10)
Sorun şu ki, eğer bir gün sınıfınız x ve y değerlerinizi bir değerle dengelemeniz gerekecek şekilde değişirse? Şimdi girmeniz ve sınıf tanımınızı ve onu çağıran tüm kodu değiştirmeniz gerekir, bu gerçekten zaman alıcı ve hataya eğilimli olabilir. Özellik, önceki sözdizimini kullanmanıza izin verirken, ikincisini değiştirme esnekliği sağlar.
Python'da, özellik işleviyle alıcıları, ayarlayıcıları ve silme yöntemlerini tanımlayabilirsiniz. Sadece read özelliğini istiyorsanız, yönteminizin üzerine ekleyebileceğiniz bir @property dekoratör de vardır.
Bernd Klein sitesinden 2 fark öğrendim :
1. Mülkiyet, veri kapsülleme yapmak için daha uygun bir yoldur.
ör .: Nesnenin genel bir öznitelik uzunluğunuz varsa, daha sonra projeniz onu kapsüllemenizi gerektirir, yani: özel olarak değiştirin ve getter ve setter => sağlayın => daha önce yazdığınız kodların çoğunu değiştirmeniz gerekir:
#Old codes
obj1.length=obj1.length+obj2.length
#New codes(Using private attibutes and getter and setter)
obj1.set_lenght(obj1.get_length()+obj2.get_length()) #=> this is ugly
@Property ve @ lenght.setter => kullanıyorsanız, bu eski kodları değiştirmeniz gerekmez
2. Bir özellik birden çok özelliği kapsayabilir
class Person:
def __init__(self, name, physic_health, mental_health):
self.name=name
self.__physic_health=physic_health #physic_health is real value in range [0, 5.0]
self.__mental_health=mental_health #mental_health is real value in range [0, 5.0]
@property
def condition(self):
health=self.__physic_health+self.__mental_health
if(health<5.0):
return "I feel bad!"
elif health<8.0:
return "I am ok!"
else:
return "Great!"
Bu örnekte __physic_healthve __mental_healthözeldir ve doğrudan dışarıdan erişilemez, sınıfın dışında onlarla etkileşim kurmanın tek yolu throught mülkiyetidir.condition
Ayrıca verileri önbelleğe almak veya yenilemek için kullandığım belirgin bir fark yok, genellikle sınıf özniteliğine bağlı bir fonksiyonumuz var. Örneğin ben bir kez dosyayı okumak ve değer önbelleğe alınır böylece özniteliğe atanan içeriği tutmak gerekir:
class Misc():
def __init__(self):
self.test = self.test_func()
def test_func(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
Çıktı:
func running
func value
func value
Özniteliğe iki kez eriştik ancak işlevimiz yalnızca bir kez tetiklendi. Özellik kullanmak için yukarıdaki örneğin değiştirilmesi, her eriştiğinizde özniteliğin değer yenilemesine neden olur:
class Misc():
@property
def test(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
Çıktı:
func running
func value
func running
func value