ITEEDU

类似C#的property概念

可以有3种方式,:

x=property(getter,setter, deleter)的方式。

property函数原型为property(fget=None,fset=None,fdel=None,doc=None),所以根据自己需要定义相应的函数即可。

@property,@x.setter,@x.deleter的方式。

__get__, __set__, __delete__的方式。

使用property()的例子:

class C(object):
   y = 3
   z = 4
   def __init__(self):
       self.__x = 2
   def getx(self):
       return self.__x
   def setx(self, val):
       print "x is read only"

    x = property(getx, setx) #这不是真正的只读属性, 虽然在setx中,没有更新__x, 但你仍可对x属性赋值, 虽然复制不生效, 但也不报错
    x = property(getx) #这是真正的只读属性, 不给属性增加setter, 这是真正的只读属性, 因为一旦要给x赋值的时候, 运行就报错
    x = property(lambda self: self.__x)#这是真正的只读属性, 因为一旦要给x赋值的时候, 运行就报错

c=C()
print(c.x,c.y,c.z)
c.x=3
print(c.x,c.y,c.z)

使用@property的例子:

class B(object):
   def __init__(self):
       self._x = None

   @property 
   def x(self): #这是x的getter
        """I'm the 'x' property."""
       return self._x
       
   @x.setter
   def x(self, value): #这是x的setter
        self._x = value

   @x.deleter
   def x(self): #这是x的deleter
        del self._x

b=B()
b.x=12
print(b.x)

使用__get__, __set__, __delete__的例子:

这种方法把每个属性做了一个类。

#!/usr/bin/env python
class Celsius(object):
    def __init__(self, value=0.0):
        self.value = float(value)
    def __get__(self, instance, owner):
        return self.value
    def __set__(self, instance, value):
        self.value = float(value)
class Farenheit(object):
    def __get__(self, instances, owner):
        return instances.celsius * 9/5 + 32
    def __set__(self, instances, value):
        instances.celsius = (float(value) - 32) * 5/9

class Temperature(object):
    celsius = Celsius()
    farenheit = Farenheit()

oven= Temperature()
oven.farenheit=450
print oven.celsius                    # 232.222222222
oven.celsius = 175
print oven.farenheit                 # 347.0

descriptor简单来看就是把对属性的访问,通过一个descriptor class来间接访问。

这个class可以有__get__, __set__, __delete__这些方法来实现属性的读,写,删除。

我们可以把相关的属性值放在descriptor class里面,比如上面例子里的class Celsius,用self.value来 保存属性值。

也可以放在descriptor class owner里面,所谓owner,就是使用descriptor class的类,就像Temperature。 例子中的class Farenheit,本身没有保存属性值,而是使用class Temperature的属性(celsius)。对于这种情况, 需要用到__get__, __set__中的第二个参数(instance)。

对比一下:

#!/usr/bin/env python
class Temperature( object ):
    def fget( self ):
        return self.celsius * 9 / 5 + 32
    def fset( self, value ):
        self.celsius= (float(value)-32) * 5 / 9
    farenheit= property( fget, fset )
    def cset( self, value ):
        self.cTemp= float(value)
    def cget( self ):
        return self.cTemp
    celsius= property( cget, cset, doc="Celsius temperature" )

oven= Temperature()
oven.farenheit= 450
print oven.celsius             # 232.222222222
oven.celsius= 175
print oven.farenheit         # 347.0