鱼C论坛

 找回密码
 立即注册
查看: 2511|回复: 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 | 显示全部楼层
class C:
    def __init__(self,name,age):
        self.name = name
        self.__age = age

        
c = C("小甲鱼",18)
hasattr(c,"name")
True
getattr(c,"name")
'小甲鱼'
getattr(c,"_C__age")
18
setattr(c,"_C__age",19)
getattr(c,"_C__age")
19
delattr(c,"_C__age")
hasattr(c,"_C__age")
False
class C:
    def __init__(self,name,age):
        self.name = name
        self.__age = age
    def __getattribute__(self,attrname):
        print("拿来吧~你~")
        return super().__getattribute__(attrname)

    
c = C("小甲鱼",18)
getattr(c,"name")
拿来吧~你~
'小甲鱼'
c._C__age
拿来吧~你~
18
c.FishC
拿来吧~你~
Traceback (most recent call last):
  File "<pyshell#21>", line 1, in <module>
    c.FishC
  File "<pyshell#17>", line 7, in __getattribute__
    return super().__getattribute__(attrname)
拿来吧~你~
拿来吧~你~
AttributeError: 'C' object has no attribute 'FishC'
class C:
    def __init__(self,name,age):
        self.name = name
        self.__age = age
    def __getattribute__(self,attrname):
        print("拿来吧~你~")
        return super().__getattribute__(attrname)
    def __getattr__(self,attrname):
        if attrname == "FishC":
            print ("I love FishC.")
        else:
            raise AttributeError(attrname)

        
c = C("小甲鱼",18)
c.FishC
拿来吧~你~
I love FishC.
c.x
拿来吧~你~
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    c.x
  File "<pyshell#28>", line 12, in __getattr__
    raise AttributeError(attrname)
拿来吧~你~
拿来吧~你~
AttributeError: x
class D:
    def __setattr__(self,name,value):
        self.__dict__[name] = value

        
d = D()
d.name = "小甲鱼"
d.name
'小甲鱼'
class D:
    def __setattr__(self,name,value):
        self.__dict__[name] = value
    def __delattr__(self,name):
        del self.__dict__[name]

        
d = D()
d.name = "小甲鱼"
d.__dict__
{'name': '小甲鱼'}
del d.name
d.__dict__
{}

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

使用道具 举报

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

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

c = C('小甲鱼', 18)
print(hasattr(c, 'name'))#True
print(getattr(c, 'name'))#小甲鱼
print(getattr(c, '_C__age'))#18
setattr(c, '_C__age', 19)
print(getattr(c, '_C__age'))#19
delattr(c, '_C__age')
print(hasattr(c, '_C__age'))#False

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

c = C('小甲鱼', 18)
print(getattr(c, 'name'))
#拿来把你~
#小甲鱼
print(c._C__age)
#拿来把你~
#18
try:
    c.Fishc
except AttributeError as e:
    print(e)
#拿来把你~
#'C' object has no attribute 'Fishc'

#__getattr__():当试图获取一个不存在的属性时触发
class C:
    def __init__(self, name, age):
        self.name = name
        self.__age = age
    def __getattribute__(self, item):
        print('拿来把你~')
        return super().__getattribute__(item)
    def __getattr__(self, item):
        if item == 'fishc':
            print('i love fishc')
        else:
            raise AttributeError(item)

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

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

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

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

d = D()
d.name = '小甲鱼'
print(d.__dict__)#{'name': '小甲鱼'}
del d.name
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-9-29 05:17

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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