Python Property – The Problem and Solution

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值