鱼C论坛

 找回密码
 立即注册
查看: 2129|回复: 13

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

[复制链接]
发表于 2022-7-25 03:58:10 | 显示全部楼层 |阅读模式
购买主题 已有 25 人购买  本主题需向作者支付 5 鱼币 才能浏览
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-9-29 19:17:39 | 显示全部楼层
Python中有4个BIF与对象的属性访问有关,分别是hasattr()、getattr()、setattr()和delattr()。顾名思义,hasattr()用于判断对象中是否拥有某属性,getattr()用于获取对象中某属性的值,setattr()用于设置对象中某属性的值,delattr()用于删除对象中的某属性。与之相对应的有4个魔法方法,分别是__getattribute__()、__getattr__()、__setattr__()和__delattr__()。其中,__getattribute__()、__setattr__()和__delattr__()分别与getattr()、setattr()和delattr()相对应,而__getattr__()则是当用户试图获取一个不存在的属性时才会被触发的魔法方法,与getattr()貌合神离,不要搞错了。此外,无论访问的属性是否存在,__getattribute__()都会优先被触发;__setattr__()和__delattr__()看似普通不过的赋值或删除操作却可能会造成无限递归的“死亡螺旋”,只有使用super()或引入__dict__后再进行相应操作,曲线救国,方能安全实现。由此可见,“魔高一尺,道高一丈。”学的越多,懂的越多,总能找到合适的方法将问题解决!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 4 反对 0

使用道具 举报

发表于 2022-10-31 16:53:22 | 显示全部楼层
小古比鱼 发表于 2022-9-29 19:17
Python中有4个BIF与对象的属性访问有关,分别是hasattr()、getattr()、setattr()和delattr()。顾名思义,ha ...

赞 小甲鱼不在跟小古比鱼混
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 1

使用道具 举报

发表于 2022-10-31 19:32:13 | 显示全部楼层
Mooven_Python 发表于 2022-10-31 16:53
赞 小甲鱼不在跟小古比鱼混

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-22 18:36:13 | 显示全部楼层
Learning...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-6 12:40:51 | 显示全部楼层
  1. class C:
  2.     def __init__(self,name,age):
  3.         self.name = name
  4.         self.__age = age

  5.         
  6. c = C("小甲鱼",18)
  7. hasattr(c,"name")
  8. True
  9. getattr(c,"name")
  10. '小甲鱼'
  11. getattr(c,"_C__age")
  12. 18
  13. setattr(c,"_C__age",19)
  14. getattr(c,"_C__age")
  15. 19
  16. delattr(c,"_C__age")
  17. hasattr(c,"_C__age")
  18. False
  19. class C:
  20.     def __init__(self,name,age):
  21.         self.name = name
  22.         self.__age = age
  23.     def __getattribute__(self,attrname):
  24.         print("拿来吧~你~")
  25.         return super().__getattribute__(attrname)

  26.    
  27. c = C("小甲鱼",18)
  28. getattr(c,"name")
  29. 拿来吧~你~
  30. '小甲鱼'
  31. c._C__age
  32. 拿来吧~你~
  33. 18
  34. c.FishC
  35. 拿来吧~你~
  36. Traceback (most recent call last):
  37.   File "<pyshell#21>", line 1, in <module>
  38.     c.FishC
  39.   File "<pyshell#17>", line 7, in __getattribute__
  40.     return super().__getattribute__(attrname)
  41. 拿来吧~你~
  42. 拿来吧~你~
  43. AttributeError: 'C' object has no attribute 'FishC'
  44. class C:
  45.     def __init__(self,name,age):
  46.         self.name = name
  47.         self.__age = age
  48.     def __getattribute__(self,attrname):
  49.         print("拿来吧~你~")
  50.         return super().__getattribute__(attrname)
  51.     def __getattr__(self,attrname):
  52.         if attrname == "FishC":
  53.             print ("I love FishC.")
  54.         else:
  55.             raise AttributeError(attrname)

  56.         
  57. c = C("小甲鱼",18)
  58. c.FishC
  59. 拿来吧~你~
  60. I love FishC.
  61. c.x
  62. 拿来吧~你~
  63. Traceback (most recent call last):
  64.   File "<pyshell#31>", line 1, in <module>
  65.     c.x
  66.   File "<pyshell#28>", line 12, in __getattr__
  67.     raise AttributeError(attrname)
  68. 拿来吧~你~
  69. 拿来吧~你~
  70. AttributeError: x
  71. class D:
  72.     def __setattr__(self,name,value):
  73.         self.__dict__[name] = value

  74.         
  75. d = D()
  76. d.name = "小甲鱼"
  77. d.name
  78. '小甲鱼'
  79. class D:
  80.     def __setattr__(self,name,value):
  81.         self.__dict__[name] = value
  82.     def __delattr__(self,name):
  83.         del self.__dict__[name]

  84.         
  85. d = D()
  86. d.name = "小甲鱼"
  87. d.__dict__
  88. {'name': '小甲鱼'}
  89. del d.name
  90. d.__dict__
  91. {}
复制代码


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-6 21:51:34 | 显示全部楼层
本帖最后由 Ensoleile 于 2023-1-10 00:32 编辑

属性访问相关的魔法方法
  1. #hasattr、getattr、setattr、delattr
  2. class C:
  3.     def __init__(self, name, age):
  4.         self.name = name
  5.         self.__age = age

  6. c = C('小甲鱼', 18)
  7. print(hasattr(c, 'name'))#True
  8. print(getattr(c, 'name'))#小甲鱼
  9. print(getattr(c, '_C__age'))#18
  10. setattr(c, '_C__age', 19)
  11. print(getattr(c, '_C__age'))#19
  12. delattr(c, '_C__age')
  13. print(hasattr(c, '_C__age'))#False

  14. #__getattribute__():当获取属性时触发,对应getattr()
  15. class C:
  16.     def __init__(self, name, age):
  17.         self.name = name
  18.         self.__age = age
  19.     def __getattribute__(self, item):
  20.         print('拿来把你~')
  21.         return super().__getattribute__(item)

  22. c = C('小甲鱼', 18)
  23. print(getattr(c, 'name'))
  24. #拿来把你~
  25. #小甲鱼
  26. print(c._C__age)
  27. #拿来把你~
  28. #18
  29. try:
  30.     c.Fishc
  31. except AttributeError as e:
  32.     print(e)
  33. #拿来把你~
  34. #'C' object has no attribute 'Fishc'

  35. #__getattr__():当试图获取一个不存在的属性时触发
  36. class C:
  37.     def __init__(self, name, age):
  38.         self.name = name
  39.         self.__age = age
  40.     def __getattribute__(self, item):
  41.         print('拿来把你~')
  42.         return super().__getattribute__(item)
  43.     def __getattr__(self, item):
  44.         if item == 'fishc':
  45.             print('i love fishc')
  46.         else:
  47.             raise AttributeError(item)

  48. c = C('小甲鱼', 18)
  49. try:
  50.     c.x#拿来把你~
  51. except AttributeError as e:
  52.     print(e)#x

  53. #__setattr__()当设置属性时触发,对应setattr()
  54. # class D:
  55. #     def __setattr__(self, name, value):
  56. #         self.name = value
  57. #
  58. # d = D()
  59. # d.name = '小甲鱼'#报错RecursionError: maximum recursion depth exceeded
  60. #捕获到赋值操作时,执行self.name = value,相当于又给自己调用了一次赋值操作,则会继续执行self.name = value,无限递归导致死循环
  61. class D:
  62.     def __setattr__(self, name, value):
  63.         self.__dict__[name] = value

  64. d = D()
  65. d.name = '小甲鱼'
  66. print(d.name)#小甲鱼

  67. #__delattr__():当一个属性被删除时触发,对应delattr()
  68. class D:
  69.     def __setattr__(self, name, value):
  70.         self.__dict__[name] = value
  71.     def __delattr__(self, item):
  72.         del self.__dict__[item]

  73. d = D()
  74. d.name = '小甲鱼'
  75. print(d.__dict__)#{'name': '小甲鱼'}
  76. del d.name
  77. print(d.__dict__)#{}
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2023-1-13 16:59:52 | 显示全部楼层
属性访问相关
class C:
    def __init__(self,name,age):
        self.name=name
        self.__age=age
c=C('小甲鱼',18)
hasattr(c,'name')
True
##检测c对象是否有name属性
getattr(c,'name')
'小甲鱼'
#获取对象的属性值
getattr(c,'_C__age')
18
setattr(c,'_C__age',19)##设定对象指定属性的值
delattr(c,'_C__age')#删除
魔法方法:
class C:
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    def __getattribute__(self,attrname):#与之对应的是__getattr__魔法方法
        print('拿来吧你')
        return super().__getattribute__(attrname)

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-2-19 11:44:03 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-5 11:28:47 | 显示全部楼层
为什么采用dict方法就可以避免死亡螺旋呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-12 21:50:47 | 显示全部楼层
小古比鱼 发表于 2022-9-29 19:17
Python中有4个BIF与对象的属性访问有关,分别是hasattr()、getattr()、setattr()和delattr()。顾名思义,ha ...

hxd,能解释下为啥用super()就能解决问题吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-13 12:27:00 | 显示全部楼层
zz子木 发表于 2023-4-12 21:50
hxd,能解释下为啥用super()就能解决问题吗

hxd,我感觉是子类里面__getattr__()、__setattr__()等等都被复写,所以返回时需要调用父类里面的方法,就是调用python原本定义方法功能来实现。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-13 23:06:43 | 显示全部楼层
本帖最后由 dearfish 于 2023-6-25 00:30 编辑

要多看几遍
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-16 15:56:42 | 显示全部楼层
笔记还不更新呀~~~~~~~~~~~~~~~·
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-6-4 05:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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