零基础入门学习Python(24):魔法方法(4)描述符

零基础入门学习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

零基础入门学习Python(24):魔法方法(3)属性访问

你可能感兴趣的:(Python零基础)