第13章 面向对象编程(16)

13.16.4 描述符

1.__get__()、__set__()和__delete__()特殊方法

>>> 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 C(object):
... 	def __init__(self, value=0.0):
... 		print 'Current is __init__'
... 		self.value = float(value)
... 	def __get__(self, instance, owner):
... 		print 'Current is __get__'
... 		return self.value
... 	def __set__(self, instance, value):
... 		print 'Current is __set__'
... 		self.value = float(value)
... 		
>>> class D(object):
... 	c = C()
... 	
Current is __init__
>>> D().c = '10'
Current is __set__
>>> D().c
Current is __get__
10.0
>>> 

描述符实际上可以是任何新式类,这种类至少实现了三个特殊方法__get__()、__set__()和__delete__()中的一个,这三个特殊方法充当描述符协议的作用。__get__()可用于得到一个属性的值,__set__()是为一个属性进行赋值的,在采用del语句(或其他,其引用计数递减)明确删除掉某个属性时会调用__delete__()方法。

还有,也不是所有的描述符都实现了__set__()方法。它们被当作方法描述符,或者更准确地说,是非数据描述符来使用。那些同时覆盖__get__()和__set__()的类被称作数据描述符。

如果你想要为一个属性写个代理,必须把它作为一个类的属性,让这个代理来为我们做所有的工作。当你用这个代理来处理对一个属性的操作时,你会得到一个描述符来代理所有的函数功能。

2. __getattribute__()特殊方法(2)

__getattribute__()因为对每个属性的实例都会调用到这个特殊的方法,这个方法被用来查找类的属性,同时也是你的一个代理,调用它可以进行属性的访问等操作。

3. 优先级别

  1. 类属性
  2. 数据描述符
  3. 实例属性
  4. 非数据描述符
  5. 默认为__getattr__()
5. 描述符总结

函数是非绑定的。虽然静态方法是在类中被定义的,它也是非绑定的。但方法必须绑定到一个实例上,类方法必须绑定到一个类上。一个函数对象的描述符可以处理这些对象,描述符会根据函数的类型确定如何“封装”这个函数和函数被绑定的对象,然后返回调用对象。函数本身就是一个描述符,函数的__get__()方法用来处理调用对象,并将调用对象返回给你。

6. 属性和property()内建函数

属性是一种有用的特殊类型的描述符。它们是用来处理所有对实例属性的访问,其工作方式和我们前面说过的描述符相似。“一般”情况下,当你使用点属性符号来处理一个实例属性时,其实你是在修改这个实例的__dict__属性。

如果我们用property()来处理这些问题,你就可以写一个和属性有关的函数来处理实例属性的获取(getting),赋值(setting)和删除(deleting)操作。

>>> class HideX(object):
... 	def __init__(self, x):
... 		self.x = x
... 	@property
... 	def fget(self):	
... 		print "Current is getter"
... 		return self.x
... 	@fget.setter
... 	def fset(self, x):
... 		print "Current is setter"
... 		assert isinstance(x, int), '"x" must be an integer!'
... 		self.x = x
... 	
>>> x = HideX(100)
>>> x.x
100
>>> x.fset = 10
Current is setter
>>> x.fget 
Current is getter
10
>>> 

>>> class C(object):
... 	def __init__(self):
... 		self._x = None
... 	def getx(self): print "Getting x"; return self._x
... 	def setx(self, value): print "setting x"; self._x = value
... 	def delx(self): print "deleting x"; del self._x
... 	x = property(getx, setx, delx, "I'm the 'x' property.")	
... 
>>> c = C()
>>> c.x = 1000
 setting x
>>> c.x
Getting x
1000
>>> del c.x
deleting x
>>> 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值