Python魔法方法之描述符

大家都知道Python有很多有趣的魔法方法,今天我们要说的是描述符这一魔法方法:

先来看一个Demo吧:

class A():
    def __init__(self):
        self.a = 10
    def getA(self):
        return self.a
    def setA(self, a):
        self.a = a
    def delA(self):
        del self.a
    '''将x与a联系起来 三个参数分别对应获得函数 赋值函数 删除函数'''
    x = property(getA,setA,delA)
if __name__ == '__main__':
    q = A()
    print(q.x)#等价于print(q.a)
    q.x = 11#等价于调用set函数赋值 q.setA(11)
    print(q.a)

在上面的模块中,我们完全可以通过操作x来替代对a的操作,这就是描述符的作用。

下面我们来看这个面塑负的实现原理:可以看到我们自定义的描述符添加了几个魔法方法,这就是描述符的原理所在了:

这我们所写的魔法方法中 instance我们就可以理解为是调用我们自定义描述符的C类的一个实例 self就是描述符本身的实例

这样去想应该就很容易理解它的原理 这几个魔法方法都是会在实例被赋值或被访问、删除是自动调用的 要不然也称不上是魔法方法,只一点要清楚

class MyProperty():
    '''在这里instance就是C类创建的一个实例 self就是x'''
    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)

最后,我们再来实现一个温度转换的功能,当然是利用描述符来实现:

稍微的来说明一下吧:一开始我们进行了赋值即 t.fan = 100 那么就会进入到Fahrenheit的__set__方法里 然后就又会转到

Celsius的__set__方法里 下一步就是print(t.cel)就会转到Celsius的__get__方法直接打印出了转换后的温度,我认为基本流层就是这样,如有错误还请评论区斧正


class Celsius():
    def __init__(self, value = 26.0):
        self.value = 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():
    '''相当于两个property'''
    cel = Celsius()
    fah = Fahrenheit()
if __name__ == '__main__':
    t = Temperature()
    t.fah = 100#赋值操作
    print(t.cel)
    t.cel = 38#赋值操作
    print(t.fah)
    

输出:

37.77777777777778
100.4

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章