property最大的用處就是能夠爲一個屬性制定getter,setter,delete和doc,他的函數原型爲:python
def __init__(self, fget=None, fset=None, fdel=None, doc=None): # known special case of property.__init__ """ property(fget=None, fset=None, fdel=None, doc=None) -> property attribute fget is a function to be used for getting an attribute value, and likewise fset is a function for setting, and fdel a function for del'ing, an attribute. Typical use is to define a managed attribute x: class C(object): def getx(self): return self._x def setx(self, value): self._x = value def delx(self): del self._x x = property(getx, setx, delx, "I'm the 'x' property.") Decorators make defining new properties or modifying existing ones easy: class C(object): @property def x(self): "I am the 'x' property." return self._x @x.setter def x(self, value): self._x = value @x.deleter def x(self): del self._x # (copied from class doc) """ pass
從上邊的代碼中能夠看出來,它一共接受4個參數,咱們再繼續看一段代碼:編程
class Rectangle(object): def __init__(self, x1, y1, x2, y2): self.x1, self.y1 = x1, y1 self.x2, self.y2 = x2, y2 def _width_get(self): return self.x2 - self.x1 def _width_set(self, value): self.x2 = self.x1 + value def _height_get(self): return self.y2 - self.y1 def _height_set(self, value): self.y2 = self.y1 + value width = property(_width_get, _width_set, doc="rectangle width measured from left") height = property(_height_get, _height_set, doc="rectangle height measured from top") def __repr__(self): return "{}({}, {}, {}, {})".format(self.__class__.__name__, self.x1, self.y1, self.x2, self.y2) rectangle = Rectangle(10, 10, 30, 15) print(rectangle.width, rectangle.height) rectangle.width = 50 print(rectangle) rectangle.height = 50 print(rectangle) print(help(rectangle))
經過property,咱們有能力創造出一個屬性來,而後爲這個屬性指定一些方法,在這裏用setter,getter的好處就是能夠監聽屬性的賦值和獲取行爲,表面上看上去上邊的代碼沒有問題,可是當出現繼承關係的時候,就出問題了。函數
class MetricRectangle(Rectangle): def _width_get(self): return "{} metric".format(self.x2 - self.x1) mr = MetricRectangle(10, 10, 100, 100) print(mr.width)
即便咱們在子類中重寫了getter方法,結果倒是無效的,這說明property只對當前的類生效,因而不得不把代碼改爲下邊這樣:code
class MetricRectangle(Rectangle): def _width_get(self): return "{} metric".format(self.x2 - self.x1) width = property(_width_get, Rectangle.width.fset) mr = MetricRectangle(10, 10, 100, 100) print(mr.width)
所以,在平時的編程中,若是須要重寫屬性的話,應該重寫該類中全部的property,不然程序很很難以理解,試想一下,setter在子類,getter在父類,多麼恐怖,orm
另外一種比較好的方案是使用裝飾器,可讀性也比較好繼承
class Rectangle(object): def __init__(self, x1, y1, x2, y2): self.x1, self.y1 = x1, y1 self.x2, self.y2 = x2, y2 @property def width(self): """rectangle width measured from left""" return self.x2 - self.x1 @width.setter def width(self, value): self.x2 = self.x1 + value @property def height(self): return self.y2 - self.y1 @height.setter def height(self, value): self.y2 = self.y1 + value def __repr__(self): return "{}({}, {}, {}, {})".format(self.__class__.__name__, self.x1, self.y1, self.x2, self.y2) rectangle = Rectangle(10, 10, 30, 15) print(rectangle.width, rectangle.height) rectangle.width = 50 print(rectangle) rectangle.height = 50 print(rectangle) print(help(rectangle))