• 类和对象11:描述符方法


    目录

    1. 描述符基础

    2. 描述符方法

    2.1 方法简述

    __get__(self, instance, owner):

    __set__(self, instance, value):

    __delete__(self, instance):

    2.2 方法参数

    2.3 简单示例

    3. 操作实例


    1. 描述符基础

    描述符(descriptor),就是将某种特殊类型的类的实例对象,赋另一个类的属性;

    描述符方法,包括 __get__、__set__、__delete__ 三种魔法方法,只有当定义它们的一个类(descriptor类)的实例对象被赋给另一个类(owner类)的类属性时使用;

    前文所学习的 property() 函数,实际上就是一个包含了三种描述符方法的描述符类; 

    注意描述符的实例对象,需要赋给类属性,访问实例层次上的描述符只会返回描述符本身,无法自动调用 __get__ 和 __set__ 方法。

    1. #创建描述符类
    2. class TestDescriptor:
    3. def __init__(self, nameinfo):
    4. self.nameinfo = nameinfo
    5. def __get__(self, instance, owner):
    6. return self.nameinfo
    7. #创建将描述符类实例对象赋给实例属性的类
    8. class TestOwner:
    9. def __init__(self, nameinfo2):
    10. self.nameinfo2 = nameinfo2
    11. self.x = TestDescriptor(self.nameinfo2)
    12. #调用由描述符类赋值的实例属性,不能正确调用魔法方法
    13. testx = TestOwner('test')
    14. testx.x
    15. <__main__.TestDescriptor object at 0x00000238691615B0>
    16. testx.x.__dict__
    17. {'nameinfo': 'test'}
    18. testx.x.nameinfo
    19. 'test'
    20. #创建将描述符类实例对象赋给类属性的类
    21. class TestOwner2:
    22. nameinfo2 = 'test'
    23. x = TestDescriptor(nameinfo2)
    24. #调用由描述符类赋值的类属性,正确调用魔法方法
    25. testy = TestOwner2()
    26. testy.y
    27. 'test'

    2. 描述符方法

    2.1 方法简述

    __get__(self, instance, owner):

    获取 owner 类或 owner 的实例(instance)属性,返回属性的值;

    __set__(self, instance, value):

    设置 owner类的一个实例对象(instance)的属性为新的 value,没有返回值;

    __delete__(self, instance):

    删除 owner类的一个实例对象(instance)的属性,没有返回值;

    2.2 方法参数

    描述符方法的各个参数说明:

    • self:descriptor类,即描述符类的实例对象;
    • instance:owner类的实例对象
    • owner:owner类
    • value:用于设置属性的值

    2.3 简单示例

    如下示例,简单表现描述符类的使用,以及描述符方法各个参数实际调用对象:

    1. #创建 descriptor 类,展示各个参数
    2. class TestDescriptor:
    3. def __get__(self, instance, owner):
    4. print(f'__get__方法各参数值为,self:{self},instance:{instance},owner:{owner}')
    5. def __set__(self, instance, value):
    6. print(f'__set__方法各参数值为,self:{self},instance:{instance},value:{value}')
    7. def __delete__(self, instance):
    8. print(f'__delete__方法各参数值为,self:{self},instance:{instance}')
    9. #创建 Owner 类,Owner 类中创建 descriptor 类的实例作为 Owner 类的一个属性
    10. class TestOwner:
    11. ins_D = TestDescriptor()
    12. #创建 Owner 类的实例
    13. ins_O = TestOwner()
    14. #Owner 类和类的实例对象
    15. ins_O
    16. <__main__.TestOwner object at 0x0000024E5B4E4F40>
    17. TestOwner
    18. <class '__main__.TestOwner'>
    19. #对 Owner 类中属性,也即 descriptor 类的实例作设置,调用 descriptor 类的 __set__ 方法
    20. class TestOwner:
    21. ins_O.ins_D = 'Testinfo: value'
    22. __set__方法各参数值为,self:<__main__.TestDescriptor object at 0x0000024E5B4A2670>,instance:<__main__.TestOwner object at 0x0000024E5B4E4F40>,value:Testinfo: value
    23. #对 Owner 类中属性,也即 descriptor 类的实例作读取,调用 descriptor 类的 __get__ 方法
    24. ins_O.ins_D
    25. __get__方法各参数值为,self:<__main__.TestDescriptor object at 0x0000024E5B4A2670>,instance:<__main__.TestOwner object at 0x0000024E5B4E4F40>,owner:<class '__main__.TestOwner'>
    26. #对 Owner 类中属性,也即 descriptor 类的实例作删除,调用 descriptor 类的 __delete__ 方法
    27. del ins_O.ins_D
    28. __delete__方法各参数值为,self:<__main__.TestDescriptor object at 0x0000024E5B4A2670>,instance:<__main__.TestOwner object at 0x0000024E5B4E4F40>

    3. 操作实例

    property 函数自行实现实操:

    1. #通过描述符类实现的类似 property 函数的 TestProperty 类
    2. class TestProperty:
    3. def __init__(self, getdef, setdef, deldef):
    4. self.getdef = getdef
    5. self.setdef = setdef
    6. self.deldef = deldef
    7. def __get__(self, instance, owner):
    8. return self.getdef(instance)
    9. def __set__(self, instance, value):
    10. self.setdef(instance,value)
    11. def __delete__(self, instance):
    12. self.deldef(instance)
    13. #调用描述符类:TestProperty,实现类似 property 函数效果
    14. class TestOwner:
    15. def __init__(self, info = 'testinfo'):
    16. self.info = info
    17. def getinfo(self):
    18. return self.info
    19. def setinfo(self, newinfo):
    20. self.info = newinfo
    21. def delinfo(self):
    22. del self.info
    23. ins_D = TestProperty(getinfo, setinfo, delinfo)
    24. #创建 TestOwner 的实例对象
    25. ins_O = TestOwner()
    26. #调用实例对象 ins_O 属性 ins_D,也即 TestProperty 的实例对象
    27. #获取 ins_O.ins_D 属性
    28. ins_O.ins_D
    29. 'testinfo'
    30. #设置 ins_O.ins_D 属性,并查询
    31. ins_O.ins_D = 'Hello, World!'
    32. ins_O.ins_D
    33. 'Hello, World!'
    34. #删除 ins_O.ins_D 属性,并验证删除成功
    35. del ins_O.ins_D
    36. ins_O.ins_D
    37. Traceback (most recent call last):
    38. File "<input>", line 1, in <module>
    39. File "<input>", line 8, in __get__
    40. File "<input>", line 21, in getinfo
    41. AttributeError: 'TestOwner' object has no attribute 'info'

    温度类实操,要求如下:

    • 定义一个温度类,然后定义两个描述符类用于描述摄氏度和华氏度两个属性;
    • 要求两个属性会自动转换,即可以给摄氏度属性赋值,获取华氏度则自动转换刚才赋值的摄氏度;
    1. #创建摄氏度描述符类
    2. class Celsius:
    3. def __init__(self, value=0.0):
    4. self.value = float(f'{value:.2f}')
    5. def __get__(self, instance, owner):
    6. return self.value
    7. def __set__(self, instance, value):
    8. self.value = float(f'{value:.2f}')
    9. #创建华氏度描述符类
    10. class Fahrenheit:
    11. def __get__(self, instance, owner):
    12. return (instance.cel * 1.8) + 32
    13. def __set__(self, instance, value):
    14. tempcel = (float(value) - 32) / 1.8
    15. instance.cel = float(f'{tempcel:.2f}')
    16. #创建温度类
    17. class Temperature:
    18. cel = Celsius()
    19. fah = Fahrenheit()
    20. #创建温度类的实例
    21. tempx = Temperature()
    22. #通过温度类的实例,对类属性 cel/fah 做读取、设置,调用魔法方法成功
    23. tempx.cel
    24. 0.0
    25. tempx.cel = 25
    26. tempx.cel
    27. 25.0
    28. tempx.fah
    29. 77.0
    30. tempx.fah = 100
    31. tempx.cel
    32. 37.78
  • 相关阅读:
    Java中的LinkedHashSet使用[71]
    CAN透传云网关给EPEC3724控制器升级方案
    Vue.js 框架源码与进阶 - Vue.js 3.0 Vite 实现原理
    framework watchdog
    Java Fasn 带您谈谈——开源、闭源
    Docker 面试题2则--取数据库连接数和docker-compose
    后端搜索条件
    2024最新版JavaScript逆向爬虫教程-------基础篇之深入JavaScript运行原理以及内存管理
    什么是指针的指针和指向函数的指针?
    zookeeper
  • 原文地址:https://blog.csdn.net/davidksatan/article/details/125612810