鱼C论坛

 找回密码
 立即注册
查看: 2652|回复: 11

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

[复制链接]
发表于 2022-9-29 05:23:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
0. 本节视频




1. 温馨提示

如果在学习本节课的过程中遇到问题,可以在这个帖子下方提问哦~


小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-9-29 19:28:53 | 显示全部楼层
打卡
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-10-7 11:23:35 | 显示全部楼层
终于学习到这里了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-10 19:25:13 | 显示全部楼层
本节继续讲解描述符,首先通过一个典型的例子说明,描述符只能应用于类属性,而不能应用于对象属性。描述符分为数据描述符和非数据描述符,前者是指实现了__set__()或__delete__()中任意一个方法的描述符,后者是指仅实现了__get__()方法的描述符。当发生属性访问时,数据描述符、实例对象属性、非数据描述符、类属性的优先级从高到低依次递减。事实上,该优先级顺序取决于管理属性获取的__getattribute__()方法的默认实现逻辑,重写该方法有望打破上述访问优先级的“碾压”。
Python3.6为描述符新添加了除__get__()、__set__()、__delete__()之外的第四个魔法方法——__set_name__(),用于捕获被描述符拦截的属性名,可使代码更为优雅,符合Python程序员一贯遵循的简洁易读的编程理念!
学完了这节课,小古比鱼有个小小的疑问:如果一个类仅仅实现了__set_name__(),而没有实现__get__()、__set__()和__delete__(),那么该类还是描述符吗?如果是,那么该类是属于数据描述符呢,还是属于非数据描述符呢?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-10 00:26:29 | 显示全部楼层
数据描述符、非数据描述符、优雅编程
  1. class D:
  2.     def __get__(self, instance, owner):
  3.         print('get~')

  4. class C:
  5.     def __init__(self):
  6.         self.x = D()

  7. c = C()
  8. print(c.x)# <__main__.D object at 0x0000020FC2EDCFA0>
  9. #描述符只能应用于类属性,而这里把它应用于对象属性,使用不会打印get~
  10. class C:
  11.     x = D()

  12. c = C()
  13. c.x# get~

  14. # 数据描述符:实现__set__()和__delete__()中的一个
  15. # 非数据描述符:仅实现__get__()方法
  16. # 当发生属性访问的时候,优先级从高到低依次是:数据描述符 -> 实例对象属性 -> 非数据描述符 -> 类属性
  17. c.x = 'fishc'
  18. print(c.x)# fishc
  19. # D为非数据描述符,优先级小于实例对象属性,所以可以更改实例对象的属性
  20. C.x# get~

  21. class D:
  22.     def __get__(self, instance, owner):
  23.         print('get~')
  24.     def __set__(self, instance, value):
  25.         print('set~')

  26. class C:
  27.     x = D()

  28. c = C()
  29. c.x = 'FishC'# set~
  30. c.x# get~
  31. print(c.__dict__)# {}
  32. # 数据描述符优先级大于实例对象属性
  33. c.__dict__['x'] = 'FishC'
  34. print(c.__dict__)# {'x': 'FishC'}
  35. c.x# get~
  36. # 拥有__set__()方法后D为数据描述符,访问对象属性依然执行优先级较高的__get__()

  37. # 优先级是定义在__getattribute__()魔法方法实现,因为其管理的是属性的获取
  38. class C:
  39.     x = D()
  40.     def __getattribute__(self, item):
  41.         print('aha~')

  42. c = C()
  43. c.x# aha~
  44. # 没有执行描述符D中的__get__()魔法方法

  45. #__set_name__(self, name, owner):描述符的第四个魔法方法 ptyhon3.6。
  46. # 前边的描述符的魔法方法__get__()、__set__()、__delete__()实现的都是对属性的拦截,在实际开发工作中,我们通过描述符去拦截一个属性,然后做了一些额外的工作,之后通常还要执行相应的访问、赋值或删除等操作。
  47. # 如我们通过描述符拦截了对象的x属性,并进行了合法性验证,判断他的值是不是大于某个值之类的操作,如果符合要求我们仍然要把它写入到实例对象的属性中去,也就是说我们需要在描述符里去操作实例对象的__dict__()字典,这其实是可以做到的,因为instance参数代表的就是描述符所拦截的属性所在的实例对象。

  48. class D:
  49.     def __init__(self, name):
  50.         self.name = name# name的作用就是记住这个描述符拦截的属性名
  51.     def __get__(self, instance, owner):
  52.         print('get~')
  53.         return instance.__dict__.get(self.name)
  54.     def __set__(self, instance, value):
  55.         print('set~')
  56.         instance.__dict__[self.name] = value

  57. class C:
  58.     x = D('x')

  59. c = C()
  60. c.x# get~
  61. #__get__()魔法方法拦截成功,此时属性x里没有内容,所以没有返回
  62. print(c.__dict__)# {}
  63. c.x = 250# set~
  64. print(c.__dict__)# {'x': 250}
  65. print(c.x)
  66. # get~
  67. # 250

  68. # class C中代码x = D('x')不够优雅,传入的属性x是以字符串'x'的形式传入。
  69. class D:
  70.     def __set_name__(self, owner, name):
  71.         self.name = name# name的作用依然是记住这个描述符拦截的属性名
  72.     def __get__(self, instance, owner):
  73.         print('get~')
  74.         return instance.__dict__.get(self.name)
  75.     def __set__(self, instance, value):
  76.         print('set~')
  77.         instance.__dict__[self.name] = value

  78. class C:
  79.     x = D()# 优雅~~~

  80. c = C()
  81. c.x# get~
  82. print(c.__dict__)# {}
  83. c.x = 250# set~
  84. print(c.__dict__)# {'x': 250}
  85. print(c.x)
  86. # get~
  87. # 250
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2023-3-1 16:53:56 | 显示全部楼层
小古比鱼 发表于 2022-10-10 19:25
本节继续讲解描述符,首先通过一个典型的例子说明,描述符只能应用于类属性,而不能应用于对象属性。描述符 ...

根据定义,数据描述符
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-4 01:40:58 | 显示全部楼层
插卡。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-7-23 17:47:10 | 显示全部楼层
小古比鱼 发表于 2022-10-10 19:25
本节继续讲解描述符,首先通过一个典型的例子说明,描述符只能应用于类属性,而不能应用于对象属性。描述符 ...

__set_name__()应该是不能单独定义的,必须跟__set__()一块使用,那就是数据描述符
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-9-8 10:30:23 | 显示全部楼层
这节课给我看懵了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-9-13 17:24:20 | 显示全部楼层
CorrineLL 发表于 2023-7-23 17:47
__set_name__()应该是不能单独定义的,必须跟__set__()一块使用,那就是数据描述符

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

使用道具 举报

发表于 2024-10-1 22:01:22 | 显示全部楼层
本帖最后由 h5531465 于 2024-10-1 22:05 编辑

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2025-2-26 15:08:20 | 显示全部楼层
python繁琐,不好用,总是有边边角角、稀奇古怪的知识点“跳”出来。比c#差得远。
不知道python好用在哪儿。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-31 22:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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