零基础入门学习Python(24):魔法方法(4)描述符
描述符就是将某种特殊类型的类的实例指派给另一个类的属性。
某种特殊类型的类指:类中要实现下面三个方法中的至少一个。
1) __get__(self, instance, owner): 用于访问属性,返回属性的值
2) __set__(self, instance, value): 在属性分配操作中调用,不返回任何内容
3) __delete__(self, instance): 控制删除操作,不返回任何内容
其中,self 指描述符类在内存中的地址,instance 指调用此描述符的类的实例对象在内存中的地址,owner 则指调用此描述符的类在内存中的地址。
之前讲过的property其实就是一个描述符类;下面通过定义自己的 property 描述符类来深入理解一下。
>>> class MyProperty: #定义自己的property类
def __init__(self,fget = None, fset = None, fdel = None):
self.fget = fget
self.fset = fset
self.fdel = fdel
def __get__(self, instance, owner): #打印出__get__()的三个参数
print('self: ', self)
print('instance: ',instance)
print('owner: ', owner)
return self.fget(instance) #返回值为调用类的fget()函数
def __set__(self, instance, value):
self.fset(instance, value)
def __delete__(self,instance):
self.fdel(instance)
>>> class Test:
def __init__(self):
self._x = None #定义一个变量,可以通过getX()得到变量x的值
def getX(self):
return self._x
def setX(self, value):
self._x = value
def delX(self):
del self._x
x = MyProperty(getX, setX, delX)
>>> test = Test() #定义一个Test类的实例
>>> test.x #调用x可以得到各个参数
self: <__main__.MyProperty object at 0x025A5870>
instance: <__main__.Test object at 0x025A5BD0>
owner: <class '__main__.Test'>
>>> test._x = 2 #设置变量
>>> test.x #通过x调用可以得到变量的值
self: <__main__.MyProperty object at 0x025A5870>
instance: <__main__.Test object at 0x025B7250>
owner: <class '__main__.Test'>
2
>>> test.x = 3 #直接设置x可以得到和设置变量_x一样的效果
>>> test._x
3
>>> del test._x #最后删除变量;此时如果再调用x,则会出错,因为已经找不到_x这个属性了
最后做个小练习:先定义一个温度类,然后定义两个描述符类用来描述摄氏度和华氏度两个属性;要求两个属性会自动进行转换,即可以给摄氏度这个属性赋值,然后打印的华氏度属性是自动转换后的结果。
>>> 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() #描述符类Celsius的实例,利用组合
fah = Fahrenheit()
>>> temp = Temperature()
>>> temp.cel #得到默认值
26.0
>>> temp.cel = 30
>>> temp.fah #Fahrenheit类中__get__()函数return中的 instance.cel 即是 temp.cel
86.0 #得到转换之后的华氏度的值
>>> temp.fah = 100 #也可以给出华氏度,得到转换之后的摄氏度的值
>>> temp.cel
37.77777777777778