鱼C论坛

 找回密码
 立即注册
查看: 2240|回复: 7

[知识点备忘] 第074讲:类和对象(XVII)

[复制链接]
发表于 2022-9-16 16:02:23 | 显示全部楼层 |阅读模式
购买主题 已有 10 人购买  本主题需向作者支付 5 鱼币 才能浏览
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-10-10 09:59:05 | 显示全部楼层
这节课讲的是一个有趣的技术——描述符,是我们前两节课所学的property()函数、类方法和静态方法背后的实现原理。描述符是指定义了__get__()、__set__()、__delete__()中任意一个或多个的类,这三个魔法方法分别用于拦截对象属性的读取、写入和删除操作,但管的是“别人家的属性”,使用时只需在另一个类中将描述符的实例化对象赋值给想要管理的属性即可。__get__()方法有三个参数:self、instance和owner。其中self对应描述符类的实例对象(被描述符拦截的属性),instance对应被描述符拦截的属性所在类的实例对象,owner对应被描述符拦截的属性所在类。借助描述符,我们不仅可以复刻之前学过的property()函数,还可以实现自己的property()函数,及其相应的getter()、setter()、deleter()方法。由此可见,描述符不愧为“木本水源”,一通百通啊!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2023-1-9 17:26:13 | 显示全部楼层
本帖最后由 Ensoleile 于 2023-1-10 00:27 编辑

描述符及property()实现原理
  1. #描述符(property的原理):P177  实现了__get__()/__set__()/__delete__()三个中任何一个或多个方法的类,称为描述符
  2. class D:
  3.     def __get__(self, instance, owner):
  4.         print(f'get~\nself -> {self}\ninstance -> {instance}\nowner -> {owner}')
  5.     def __set__(self, instance, value):
  6.         print(f'set~\nself -> {self}\ninstance -> {instance}\nvalue -> {value}')
  7.     def __delete__(self, instance):# 不要混淆__del__()
  8.         print(f'delete~\nself -> {self}\ninstance -> {instance}')

  9. # 类D 为描述符,在另一个类里将他的实例化对象赋值给想要管理的属性就能启用他
  10. class C:
  11.     x = D()

  12. c = C()
  13. c.x = 250
  14. # set~
  15. # self -> <__main__.D object at 0x0000028D56A88FA0>
  16. # instance -> <__main__.C object at 0x0000028D56A88F70>
  17. # value -> 250
  18. c.x
  19. # get~
  20. # self -> <__main__.D object at 0x0000026F6A728FA0>
  21. # instance -> <__main__.C object at 0x0000026F6A728F70>
  22. # owner -> <class '__main__.C'>
  23. del c.x
  24. # delete~
  25. # self -> <__main__.D object at 0x0000026F6A728FA0>
  26. # instance -> <__main__.C object at 0x0000026F6A728F70>

  27. # self参数对应的是描述符这个类的实例对象<__main__.D object at 0x0000026F6A728FA0>
  28. # instance对应的是被描述符拦截的属性所在的类的实例对象<__main__.C object at 0x0000026F6A728F70>
  29. # owner参数对应被描述符拦截的属性所在的类<class '__main__.C'>

  30. # 将案例修改为描述符的实现方式
  31. ######################案例##########################
  32. # class C:
  33. #     def __init__(self):
  34. #         self._x = 250
  35. #     def getx(self):
  36. #         return self._x
  37. #     def setx(self, value):
  38. #         self._x = value
  39. #     def delx(self):
  40. #         del self._x
  41. #     x = property(getx, setx, delx)
  42. #
  43. # c = C()
  44. # print(c.x)#250
  45. # c.x = 520
  46. # print(c.x)#520
  47. # del c.x
  48. # print(c.__dict__)#{}
  49. #########################################################
  50. class D:
  51.     def __get__(self, instance, owner):
  52.         return instance._x
  53.     def __set__(self, instance, value):
  54.         instance._x = value
  55.     def __delete__(self, instance):
  56.         del instance._x

  57. class C:
  58.     def __init__(self, x=250):
  59.         self._x = x
  60.     x = D()

  61. c = C()
  62. print(c.x)#250
  63. c.x = 520
  64. print(c.x)#520
  65. del c.x
  66. print(c.__dict__)#{}
  67. # 代码虽然能实现但不是一段健康的代码,类D中使用了类C中的属性_x

  68. # property()的原理
  69. class PropertyL:
  70.     def __init__(self, fget=None, fset=None, fdel=None):
  71.         self.fget = fget
  72.         self.fset = fset
  73.         self.fdel = fdel
  74.     def __get__(self, instance, owner):
  75.         return self.fget(instance)
  76.     def __set__(self, instance, value):
  77.         self.fset(instance, value)
  78.     def __delete__(self, instance):
  79.         self.fdel(instance)

  80. class C:
  81.     def __init__(self):
  82.         self._x = 250
  83.     def getx(self):
  84.         return self._x
  85.     def setx(self, value):
  86.         self._x = value
  87.     def delx(self):
  88.         del self._x
  89.     p = PropertyL(getx, setx, delx)

  90. c = C()
  91. print(c.p)#250
  92. c.p = 520
  93. print(c.p)#520
  94. del c.p
  95. print(c.__dict__)#{}

  96. #实现getter()、setter()、deleter()方法
  97. class PropertyL:
  98.     def __init__(self, fget=None, fset=None, fdel=None):
  99.         self.fget = fget
  100.         self.fset = fset
  101.         self.fdel = fdel
  102.     def __get__(self, instance, owner):
  103.         return self.fget(instance)
  104.     def __set__(self, instance, value):
  105.         self.fset(instance, value)
  106.     def __delete__(self, instance):
  107.         self.fdel(instance)
  108.     def getter(self, func):
  109.         self.fget = func
  110.         return self
  111.     def setter(self, func):
  112.         self.fset = func
  113.         return self
  114.     def deleter(self, func):
  115.         self.fdel = func
  116.         return self

  117. class D:
  118.     def __init__(self):
  119.         self._x = 250
  120.     @PropertyL
  121.     def x(self):
  122.         return self._x
  123.     @x.setter
  124.     def x(self, value):
  125.         self._x = value
  126.     @x.deleter
  127.     def x(self):
  128.         del self._x

  129. d = D()
  130. print(d.x)# 250
  131. d.x = 520
  132. print(d.__dict__)# {'_x': 520}
  133. del d.x
  134. print(d.__dict__)# {}
  135. #另一种写法
  136. class E:
  137.     def __init__(self):
  138.         self._x = 250
  139.     x = PropertyL()
  140.     @x.getter
  141.     def x(self):
  142.         return self._x
  143.     @x.setter
  144.     def x(self, value):
  145.         self._x = value
  146.     @x.deleter
  147.     def x(self):
  148.         del self._x

  149. e = E()
  150. print(e.x)# 250
  151. e.x = 520
  152. print(e.__dict__)# {'_x': 520}
  153. del e.x
  154. print(e.__dict__)# {}
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2023-2-26 15:36:11 | 显示全部楼层
本帖最后由 我又可以了 于 2023-2-28 14:44 编辑
  1. class D:
  2.         def __get__(self,instance,owner):
  3.                 return instance._x
  4.         def __set__(self,instance,value):
  5.                 instance._x=value
  6.         def __delete__(self,instance):
  7.                 del instance._x

  8.                
  9. >>> class C:
  10.         def __init__(self):
  11.                 self._x=250
  12.         x=D()

  13.        
  14. >>> c=C()
  15. >>> c.x
  16. 250
  17. >>> c.x=520
  18. >>> c.__dict__
  19. {'_x': 520}
  20. >>> del c.x
  21. >>> c.__dict__
  22. {}
复制代码

WM
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-15 09:30:55 | 显示全部楼层
Ensoleile 发表于 2023-1-9 17:26
描述符及property()实现原理

大佬,我想给78-80加一个注解:
print(self.fget)#C.getx
print(self.fset)#C.setx
print(self.fdel)#C.delx
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-10 09:00:13 | 显示全部楼层
太强了,yyds,老哥。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-12 16:47:05 | 显示全部楼层
这节看不懂,,
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-17 12:55:33 | 显示全部楼层
今天课程又补充完善了!
编程其实挺难的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-22 07:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表