三国纷争
该property()函数返回一个特殊的描述符对象:>>> property()<property object at 0x10ff07940>正是这种对象有额外的方法:>>> property().getter<built-in method getter of property object at 0x10ff07998>>>> property().setter<built-in method setter of property object at 0x10ff07940>>>> property().deleter<built-in method deleter of property object at 0x10ff07998>这些充当装饰过。他们返回一个新的属性对象:>>> property().getter(None)<property object at 0x10ff079f0>那是旧对象的副本,但是替换了其中一个功能。记住,@decorator语法只是语法糖。语法:@propertydef foo(self): return self._foo确实与def foo(self): return self._foofoo = property(foo)因此foo该函数被替换了property(foo),我们在上面看到的是一个特殊的对象。然后,当您使用时@foo.setter(),您正在做的事情就是调用property().setter我上面显示的方法,该方法将返回该属性的新副本,但这一次是将setter函数替换为装饰方法。下面的序列还通过使用那些装饰器方法创建了一个全开属性。首先,我们创建一些函数和一个property仅带有吸气剂的对象:>>> def getter(self): print('Get!')... >>> def setter(self, value): print('Set to {!r}!'.format(value))... >>> def deleter(self): print('Delete!')... >>> prop = property(getter)>>> prop.fget is getterTrue>>> prop.fset is NoneTrue>>> prop.fdel is NoneTrue接下来,我们使用该.setter()方法添加一个setter:>>> prop = prop.setter(setter)>>> prop.fget is getterTrue>>> prop.fset is setterTrue>>> prop.fdel is NoneTrue最后,我们使用以下.deleter()方法添加删除器:>>> prop = prop.deleter(deleter)>>> prop.fget is getterTrue>>> prop.fset is setterTrue>>> prop.fdel is deleterTrue最后但并非最不重要的,property对象作为一个描述符对象,所以它有.__get__(),.__set__()和.__delete__()方法挂接到实例属性获取,设置和删除:>>> class Foo: pass... >>> prop.__get__(Foo(), Foo)Get!>>> prop.__set__(Foo(), 'bar')Set to 'bar'!>>> prop.__delete__(Foo())Delete!Descriptor Howto包括以下类型的纯Python示例实现property():class Property: "Emulate PyProperty_Type() in Objects/descrobject.c" def __init__(self, fget=None, fset=None, fdel=None, doc=None): self.fget = fget self.fset = fset self.fdel = fdel if doc is None and fget is not None: doc = fget.__doc__ self.__doc__ = doc def __get__(self, obj, objtype=None): if obj is None: return self if self.fget is None: raise AttributeError("unreadable attribute") return self.fget(obj) def __set__(self, obj, value): if self.fset is None: raise AttributeError("can't set attribute") self.fset(obj, value) def __delete__(self, obj): if self.fdel is None: raise AttributeError("can't delete attribute") self.fdel(obj) def getter(self, fget): return type(self)(fget, self.fset, self.fdel, self.__doc__) def setter(self, fset): return type(self)(self.fget, fset, self.fdel, self.__doc__) def deleter(self, fdel): return type(self)(self.fget, self.fset, fdel, self.__doc__)