小甲鱼python046魔法方法:描述符(property 的原理)

0 总结

0.0 描述符

描述符就是将某种特殊类型的类的实例指派给另一个类的属性
特殊类型的要求,至少实现以下三个方法:

  1. __get__(self, instance, owner)
    用于访问属性,它返回属性的值
  2. __set__(self, instance, value)
    将在属性分配操作中调用,不返回任何内容
  3. __delete__(self, instance)
    控制删除操作,不返回任何内容

e.g.

>>> class MyDescriptor:
	def __get__(self, instance, owner):
		print("getting...", self, instance, owner)
	def __set__(self, instance, value):
		print("setting...", self, instance, value)
	def __delete__(self, instance):
		print("deleting...", self, instance)
>>> class Test:
	x = MyDescriptor()
>>> test = Test()
>>> test.x
getting... <__main__.MyDescriptor object at 0x0000000002FF0080> <__main__.Test object at 0x0000000002FACCC0> <class '__main__.Test'>
>>> test
<__main__.Test object at 0x0000000002FACCC0>
>>> test.x = 'fuck'
setting... <__main__.MyDescriptor object at 0x0000000002FF0080> <__main__.Test object at 0x0000000002FACCC0> fuck
>>> del test.x
deleting... <__main__.MyDescriptor object at 0x0000000002FF0080> <__main__.Test object at 0x0000000002FACCC0>

0.1 MyProperty

>>> class MyProperty:
	def __init__(self, fget=None, fset=None, fdel=None):
		self.fget = fget
		self.fset = fset
		self.fdel = fdel

	def __get__(self, instance, owner):
		return self.fget(instance)
	def __set__(self, instance, value):
		self.fset(instance, value)
	def __delete__(self, instance):
		self.fdel(instance)
>>> class C:
	def __init__(self):
		self._x = None
	def getX(self):
		return self._x
	def setX(self, value):
		self._x = value
	def delX(self):
		del self._x
	x = MyProperty(getX, setX, delX)
>>> c=C()
>>> c.x = 'fuck'
>>> c.x
'fuck'

0.2 案例:温度计

  • 定义一个温度类,然后定义两个描述符类用于描述摄氏度和华氏度两个温度。
  • 要求两个属性会自动进行转化,也就是说你可以給摄氏度这个属性赋值,然后打印的华氏度属性是自动转换后的结果。
class Celsius:
    def __init__(self, value = 26.0):
        self.value = float(value)
    def __get__(self, instance, owner):
        return self.value
    def __set__(self, instance, value):
        self.value = float(value)

class Fahrenheit:
    def __get__(self, instance, owner):
        return instance.cel * 1.8 + 32
    def __set__(self, instance, value):
        instance.cel = (float(value) - 32) / 1.8
        
class Temperature:
    cel = Celsius()
    fah = Fahrenheit()
    
>>> temp = Temperature()
>>> temp.cel
26.0
>>> temp.cel = 100
>>> temp.fah
212.0

1 课后习题

1.0 测试题

小甲鱼python046魔法方法:描述符(property 的原理)
小甲鱼python046魔法方法:描述符(property 的原理)
小甲鱼python046魔法方法:描述符(property 的原理)