(1) 从instance改成self. 此时数据将会存储在weight和price实例中
(2) 创建2个托管实例,truffle和truffle1
(3) 在第一个托管实例truffle中设置weigh值
(4) 并在第二个托管实例truffle1中查看对应的值,发现weight值也变成了2。这也应证了前面说的如果数值存储在描述符实例中的话,所有LineItem都会访问到
在上一章中讲到如果通过实例读取属性的时候,通常返回的是实例中定义的属性。但是如果实例中没有指定的属性。那么回获取类属性,而再给实例中的属性赋值的时候,通常会在实例中创建属性,根本不影响类。这种处理方式对于描述符也是一样的。根据是否定义了__set__方法,描述符分为两大类。一个是覆盖型的,一种是非覆盖型的
来看下代码:
class Overriding(object): def __get__(self, instance, owner): print 'get',self,instance,owner def __set__(self, instance, value): print 'get',self,instance,valueclass OverrideNoGet(object): def __set__(self, instance, value): print 'set',self,instance,valueclass NonOverriding(object): def __get__(self, instance, owner): print 'get',self,instance,ownerclass Managed(object): over=Overriding() over_no_get=OverrideNoGet() non_over=NonOverriding()
实现了__set__方法的描述符属于覆盖型描述符。因此虽然描述符是类属性。但是实现__set__方法的话。会覆盖对实例属性的赋值操作。首先来看下 Overriding
if __name__=="__main__": obj=Managed() print obj.over (1) print Managed.over (2) obj.over=9 obj.over (3) obj.__dict__['over']=8 (4) print vars(obj) obj.over (5) E:\python2.7.11\python.exe E:/py_prj/fluent_python/chapter20.py get <__main__.Overriding object at 0x016AF450> <__main__.Managed object at 0x016AF4B0> <class '__main__.Managed'> None get <__main__.Overriding object at 0x016AF450> None <class '__main__.Managed'> None set <__main__.Overriding object at 0x016AF450> <__main__.Managed object at 0x016AF4B0> 9 get <__main__.Overriding object at 0x016AF450> <__main__.Managed object at 0x016AF4B0> <class '__main__.Managed'> {'over': 8} get <__main__.Overriding object at 0x016AF450> <__main__.Managed object at 0x016AF4B0> <class '__main__.Managed'>(1) obj.over触发描述符的__get__方法。第二个参数是托管实例的obj
(2) Managed.over触发描述符的__get__方法。第二个参数是None
(3) obj.over=9 触发描述符__set__方法。但是在obj.over的时候依然触发的是__get__方法
(4) 跳过描述符,直接通过obj.__dict__属性设值
(5) Vars(obj)确认over的值在__dict__属性中。但是obj.over依然触发的是__get__方法。依然被描述符所覆盖
OverrideNoGet是没有实现__get__的覆盖性描述符,因为有实现__set__。所以只有写操作由描述符处理。通过实例读取描述符会返回描述符对象本身。
if __name__=="__main__": obj=Managed() print obj.over_no_get (1) obj.over_no_get=7 (2) print obj.over_no_get obj.__dict__['over_no_get']=9 (3) print obj.over_no_get (4) obj.over_no_get=7 print obj.over_no_get (5)E:\python2.7.11\python.exe E:/py_prj/fluent_python/chapter20.py
<__main__.OverrideNoGet object at 0x0167F470>
set <__main__.OverrideNoGet object at 0x0167F470> <__main__.Managed object at 0x0167F4B0> 7
<__main__.OverrideNoGet object at 0x0167F470>
9
set <__main__.OverrideNoGet object at 0x0167F470> <__main__.Managed object at 0x0167F4B0> 7
9
(1) 因为没有__get__方法,因为从类中获取实例属性
(2) obj.over_no_get=7触发__set__方法
(3) 通过实例的__dict__属性设置名为over_no_get的实例属性
(4) 访问obj.over_no_get的时候实例属性会覆盖描述符
(5) 但是在obj.over_no_get=7依然触发的是__set__方法。只有在读取的时候,只要有同名的实例属性,描述符就会被遮盖
最后来看下NonOverriding,只实现了__get__方法,而没有__set__方法。属于非覆盖型描述符。如果设置了同名的实例属性。描述符会被覆盖。致使描述符无法处理那个实例的的属性。 obj=Managed() obj.non_over (1) obj.non_over=9 (2)print obj.non_over (3)del obj.non_over obj.non_over (4) E:\python2.7.11\python.exe E:/py_prj/fluent_python/chapter20.py get <__main__.NonOverriding object at 0x016BF470> <__main__.Managed object at 0x016BF490> <class '__main__.Managed'> 9 get <__main__.NonOverriding object at 0x016BF470> <__main__.Managed object at 0x016BF490> <class '__main__.Managed'>
(1) obj.over触发描述符的__get__方法。
(2) 因为没有__set__方法。Obj.non_over=9的时候无法触发__set__方法。
(3) 访问obj.non_over的时候访问的是实例属性,而把Managed类的同名描述符属性遮盖掉
(4) 在删除了obj.non_over的时候,也就是对应的实例属性被删除了。再次访问obj.non_over的时候,会触发描述符__get__方法。
转载于:https://www.cnblogs.com/zhanghongfeng/p/7479233.html