- 论坛徽章:
- 0
|
最近看django源码的时候发现了python的descriptor,以前从来没有涉及过,(python的基础真是差啊,我),所以来学习一下。
参考了:http://users.rcn.com/python/download/Descriptor.htm
http://blog.chinaunix.net/u/23216/showart_189009.html
http://www.javaeye.com/wiki/Python/1362-python-39-s-descriptor
http://docs.python.org/reference/datamodel.html#implementing-descriptors
descriptor实际上就是一个类的属性,只不过这个属性定义了__get__,__set__,__del__这三个方法中的一个或者多个(最少要有__get__),然后当这个类的对象调用这个属性的时候就会相应的调用__get__或者__set__或者__del__。只定义了__get__方法的descriptor是non-data descriptor,定义了__set__的是data-descriptor。
descriptor只能被一个新式的类或者类对象调用。(新式的类就是从objct或者type继承的类)。
类和类的对象都有__dict__,调用类对象的属性时:对于obj.x,优先查找obj.__dict__["x"],如果找不到,再查找class.__dict__["x"];调用类的属性时;对于class.x,直接查找class.__dict__["x"];obj.__dict__与class.__dict__可以拥有同名的属性;obj.x=10,将无条件的更新obj.__dict__;class.x=10,将无条件的更新class.__dict__。这里在掉用__dict__['x']的时候按照以下优先级:
data descriptor高于obj.__dict__['x']高于non-data descriptor。
我自己做了一些实验,感觉和javaeye以及chinaunix里面的两篇文章多少都有一些不一样(虽然这两篇文章好些写的一些细节也不一样)。
代码如下:(data-descriptor)
#coding:utf-8
class AA(object):
def __init__(self):
self.value = 25
def __get__(self, ownerobj, ownerclass):
print "it is in ", ownerobj, "get"
print "value is ", str(self.value)
return self.value
def __set__(self, ownerobj, value):
print "it is in ", ownerobj, "set"
print "original value is ", self.value
print "now value is ", value
self.value = value
def __delete__(self, ownerobj):
pass
class CC(object):
x = 5
aobj = AA()
c = CC()
CC.aobj
c.aobj
print ">>>"*3
c.aobj = 15 #因为是data descriptor,而且c.__dict__中没有aobj这个键名,所以这里调用的是CC.__dict__['aobj'].__set__
CC.aobj #这里调用的是CC.__dict__['aobj'].__get__
c.aobj #因为c.__dict__中没有aobj这个键名,所以这里调用的是CC.__dict__['aobj'].__get__
print ">>>"*3 #注意:以下三行的解释可能有误,里买的值是对的,但是没有打印动作发生,不知道问什么,希望知道的高手给个解答。
CC.aobj = 35 #因为是data descriptor,而且c.__dict__中没有aobj这个键名,所以这里调用的是CC.__dict__['aobj'].__set__
CC.aobj #这里调用的是CC.__dict__['aobj'].__get__,值是35。
c.aobj #因为c.__dict__中没有aobj这个键名,所以这里调用的是CC.__dict__['aobj'].__get__,值是35。
运行结果为:
it is in None get
value is 25
it is in get
value is 25
>>>>>>>>>
it is in set
original value is 25
now value is 15
it is in None get
value is 15
it is in get
value is 15
>>>>>>>>>
non-data descriptor代码为:
#coding:utf-8
class AA(object):
def __init__(self):
self.value = 25
def __get__(self, ownerobj, ownerclass):
print "it is in ", ownerobj, "get"
print "value is ", str(self.value)
return self.value
# def __set__(self, ownerobj, value):
# print "it is in ", ownerobj, "set"
# print "original value is ", self.value
# print "now value is ", value
# self.value = value
# def __delete__(self, ownerobj):
# pass
class CC(object):
x = 5
aobj = AA()
c = CC()
CC.aobj
c.aobj
print ">>>"*3
c.aobj = 15 #因为是non-data descriptor直接设置了c.__dict__
CC.aobj #调用的是CC.__dict__['aobj'].__get__,他返回的是关于CC类的,而不是上面对c设置的15
c.aobj #因为是non-data descriptor,他调用的是c.__dict__中的值,所以没有print行为发生
print ">>>"*3
CC.aobj = 35 #设置的是CC.__dict__中的值
CC.aobj #在这里是从CC.__dict__中直接取的属性值,所以没有print行为发生他的值是刚才设置的35
c.aobj #因为是non-data descriptor,所以这里调用的是c.__dict__中的值,没有print行为发生。其值上面c.aobj=15设置的15
运行结果为:
it is in None get
value is 25
it is in get
value is 25
>>>>>>>>>
it is in None get
value is 25
>>>>>>>>>
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/103690/showart_2156248.html |
|