zoukankan      html  css  js  c++  java
  • 第46讲:魔方方法——描述符(property的原理)

    一 描述符相关知识

    1 定义:描述符就是将某种特殊类型的类的实例指派给另一个类的属性

    • 特殊类型的类要满足的条件是:至少要实现以下三个方法其中一个
      • __get__(self,instance,owner):用于访问属性,它返回属性的值
      • __set__(self,instance,value):将在属性分配(赋值)操作中调用,不返回任何内容
      • __delete__(self,instance):控制删除操作,不返回任何内容

    2 举例:property函数的实现

     1 >>> class MyProperty(object):
     2 ...     def __init__(self,fget=None,fset=None,fdel=None):
     3 ...             self.fget = fget
     4 ...             self.fset = fset
     5 ...             self.fdel = fdel
     6 ...     def __get__(self,instance,owner):
     7 ...             return self.fget(instance)
     8 ...     def __set__(self,instance,value):
     9 ...             self.fset(instance,value)
    10 ...     def __del__(self,instance):        # 注意,这里应该用delete,不是缩写,否则后面会报错
    11 ...             self.fdel(instance)
    12 ...
    13 >>> class C(object):
    14 ...     def __init__(self):
    15 ...             self._x = None
    16 ...     def getX(self):
    17 ...             return self._x
    18 ...     def setX(self,value):
    19 ...             self._x = value
    20 ...     def delX(self):            
    21 ...             del self._x
    22 ...     x = MyProperty(getX,setX,delX)
    23 ...
    24 >>> c = C()
    25 >>> c.x = "abc"
    26 >>> c.x
    27 'abc'
    28 >>> c._x
    29 'abc'
    30 >>> del c._x
    31 >>> del c.x
    32 Traceback (most recent call last):
    33   File "<stdin>", line 1, in <module>
    34 AttributeError: __delete__

    3 练习

    要求:

    • 先定义一个温度类,然后定义两个描述符类,用于描述摄氏度和华氏度两个属性
    • 要求两个属性会自动进行转换,也就是说你可以给摄氏度这个属性赋值,然后打印的华氏度属性是自动转换后的结果

    代码:

     1 class Celsius(object):
     2     def __init__(self,value = 26.0):
     3         self.value = float(value)
     4     def __get__(self,instance,owner):
     5         return self.value
     6     def __set__(self,instance,value):
     7         self.value = float(value)
     8 
     9 class Fahrenheit(object):
    10     def __get__(self,instance,owner):
    11         return instance.cel * 1.8 + 32             # 完成摄氏度到华氏度的转换
    12     def __set__(self,instance,value):
    13         instance.cel = (float(value) - 32) / 1.8   # 完成华氏度到摄氏度的转换
    14 
    15 # 描述符类
    16 class Temperature(object):
    17     cel = Celsius()        # cel是类Temperature的属性,但同时它也是Celsius类的实例
    18     fah = Fahrenheit()

    执行结果:

     1 >>> import class46_Temp as T
     2 >>> temp = T.Temperature()
     3 >>> temp.cel
     4 26.0
     5 >>> temp.fah
     6 78.80000000000001
     7 >>> temp.cel = 30
     8 >>> temp.fah
     9 86.0
    10 >>> temp.fah = 100
    11 >>> temp.cel
    12 37.77777777777778

    执行过程:

    temp.fah ——访问Temperature类的fah属性,该属性是Fahrenheit类的实例,此时会调用Fahrenheit类的__get__方法,从而计算出默认的摄氏度26对应的华氏度的值:78.80000000000001

    temp.cel = 30 ——对Temperature类的cel属性进行赋值,该属性是Celsius类的实例,此时会调用Celsius类的__set__方法,将self.value的值赋值为30,然后再通过temp.fah访问fah属性,得到30对应的华氏度的值:86.0

    temp.fah = 100 ——对Temperature类的fah属性进行赋值,该属性是Fahrenheit类的实例,此时会调用Fahrenheit类的__set__方法,计算华氏度100对应的摄氏度的值:37.77777777777778,并将计算结果赋值给instance.cel也就是temp.cel;因为此时进行了赋值操作,相当于调用了Celsius类的__set__方法,将计算后的结果37.77777777777778转化为浮点数存储在self.value里面。

  • 相关阅读:
    OSG嵌入QT(QT界面使用Qt Designer编辑)
    C++ Makefile文件编写
    cbp2make使用
    for循环之后的return
    C++引用形参,函数返回多个值
    个人感悟之代理模式
    个人感悟之单例模式
    个人感悟之简单工厂模式-工厂方法模式-抽象工厂模式
    Java设计模式
    (转)java之Spring(IOC)注解装配Bean详解
  • 原文地址:https://www.cnblogs.com/luoxun/p/13642268.html
Copyright © 2011-2022 走看看