https://data-flair.training/blogs/python-property-problem-solution/
>> class Song:
def __init__(self ,title):
self.title = title
def show_title(self):
print("I'm listening to ",self.title)
>>> Teddy_Bear=Song('Teddy Bear')
>>> Teddy_Bear.show_title()
I'm listening to Teddy Bear
>>> Teddy_Bear.title #getting the title
'Teddy Bear'
>>> Teddy_Bear.title='OK BEAR' #setting the title
>>>
>>> Teddy_Bear.title
'OK BEAR'
>>> Teddy_Bear.__dict__
{'title': 'OK BEAR'}
>>>
eg :
class Person(object):
""""""
#----------------------------------------------------------------------
def __init__(self, first_name, last_name):
"""Constructor"""
self.first_name = first_name
self.last_name = last_name
#----------------------------------------------------------------------
@property
def full_name(self):
"""
Return the full name
"""
return "%s %s" % (self.first_name, self.last_name)
>>> person = Person("Mike", "Driscoll")
>>> person.full_name
'Mike Driscoll'
>>> person.first_name
'Mike'
>>> person.full_name = "Jackalope"
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
person.full_name = "Jackalope"
AttributeError: can't set attribute
>>>
>>>
正如你所看到的,因为我们将方法变成了属性,我们可以使用正常的点符号访问它。但是,如果我们试图将该属性设为其他值,我们会引发一个AttributeError错误。改变full_name属性的唯一方法是间接这样做:
>>> person.first_name = "Dan"
>>> person.full_name
'Dan Driscoll'
>>>
使用Python property取代setter和getter方法
让我们假设我们有一些遗留代码,它们是由一些对Python理解得不够好的人写的。如果你像我一样,你之前已经看到过这类的代码:
from decimal import Decimal
########################################################################
class Fees(object):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self._fee = None
#----------------------------------------------------------------------
def get_fee(self):
"""
Return the current fee
"""
return self._fee
#----------------------------------------------------------------------
def set_fee(self, value):
"""
Set the fee
"""
if isinstance(value, str):
self._fee = Decimal(value)
elif isinstance(value, Decimal):
self._fee = value
要使用这个类,我们必须要使用定义的getter和setter方法:
>>> f = Fees()
>>> f.set_fee("1")
>>>
>>> f.get_fee()
Decimal('1')
但是,如果想这样呢:
>>> f.fee
Traceback (most recent call last):
File "<pyshell#15>", line 1, in <module>
f.fee
AttributeError: 'Fees' object has no attribute 'fee'
>>>
就得加一句:
fee = property(get_fee, set_fee)
>>> f = Fees()
>>> f.set_fee("1")
SyntaxError: unexpected indent
>>> f.set_fee("1")
>>> f.fee
Decimal('1')
>>>
>>> f.fee = "2"
>>> f.get_fee()
Decimal('2')
>>> f.fee
Decimal('2')
>>>
正如你所看到的,当我们以这种方式使用属性函数时,它允许fee属性设置并获取值本身而不破坏原有代码。让我们使用属性装饰器来重写这段代码,看看我们是否能得到一个允许设置的属性值。
from decimal import Decimal
########################################################################
class Fees(object):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self._fee = None
#----------------------------------------------------------------------
@property
def fee(self):
"""
The fee property - the getter
"""
return self._fee
#----------------------------------------------------------------------
@fee.setter
def fee(self, value):
"""
The setter of the fee property
"""
if isinstance(value, str):
self._fee = Decimal(value)
elif isinstance(value, Decimal):
self._fee = value
#----------------------------------------------------------------------
if __name__ == "__main__":
f = Fees()
f = Fees()
f.fee = “1”
f.fee
Decimal(‘1’)
如果你看属性函数的说明,它有fget, fset, fdel和doc几个参数。如果你想对属性使用del命令,你可以使用@fee.deleter创建另一个装饰器来装饰相同名字的函数从而实现删除的同样效果。
另外一个例子:
# Python program to explain property() function
# Alphabet class
class Alphabet:
def __init__(self, value):
self._value = value
# getting the values
def getValue(self):
print('Getting value')
return self._value
# setting the values
def setValue(self, value):
print('Setting value to ' + value)
self._value = value
# deleting the values
def delValue(self):
print('Deleting value')
del self._value
value = property(getValue, setValue, delValue, )
x = Alphabet('GeeksforGeeks')
print(x.value)
=============== RESTART: E:/practise/python/proprerty_geek.py ===============
Getting value
GeeksforGeeks
>>>
x.value = 'GfG'
Setting value to GfG
del x.value
Deleting value
# Python program to explain property()
# function using decorator
class Alphabet:
def __init__(self, value):
self._value = value
# getting the values
@property
def value(self):
print('Getting value')
return self._value
# setting the values
@value.setter
def value(self, value):
print('Setting value to ' + value)
self._value = value
# deleting the values
@value.deleter
def value(self):
print('Deleting value')
del self._value
# passing the value
x = Alphabet('Peter')
print(x.value)
x.value = 'Diesel'
del x.value
Output:
Getting value
Peter
Setting value to Diesel
Deleting value
Using @property decorator works same as property() method.
First, specify that value() method is also an attribute of Alphabet then, we use the attribute value to specify the setter and the deleter. Notice that the same method value() is used with different definitions for defining the getter, setter and deleter. Whenever we use x.value, it internally calls the appropriate getter, setter and deleter.
Applications:
By using property() method, we can modify our class and implement the value constraint without any change required to the client code. So that the implementation is backward compatible.