小甲鱼 发表于 2022-7-25 03:58:10

已有 25 人购买  本主题需向作者支付 5 鱼币 才能浏览 购买主题

小古比鱼 发表于 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__后再进行相应操作,曲线救国,方能安全实现。由此可见,“魔高一尺,道高一丈。”学的越多,懂的越多,总能找到合适的方法将问题解决!

Mooven_Python 发表于 2022-10-31 16:53:22

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

赞 小甲鱼不在跟小古比鱼混

小古比鱼 发表于 2022-10-31 19:32:13

Mooven_Python 发表于 2022-10-31 16:53
赞 小甲鱼不在跟小古比鱼混

{:5_92:}

migu_sm1 发表于 2022-11-22 18:36:13

Learning...{:10_249:}

migu_sm1 发表于 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__ = value

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

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

Ensoleile 发表于 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__ = value

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

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

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

yukari123 发表于 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)

wanglyndon 发表于 2023-2-19 11:44:03

{:10_279:}

1137687803 发表于 2023-4-5 11:28:47

为什么采用dict方法就可以避免死亡螺旋呢

zz子木 发表于 2023-4-12 21:50:47

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

hxd,能解释下为啥用super()就能解决问题吗

Axiujiu 发表于 2023-4-13 12:27:00

zz子木 发表于 2023-4-12 21:50
hxd,能解释下为啥用super()就能解决问题吗

hxd,我感觉是子类里面__getattr__()、__setattr__()等等都被复写,所以返回时需要调用父类里面的方法,就是调用python原本定义方法功能来实现。

dearfish 发表于 2023-6-13 23:06:43

本帖最后由 dearfish 于 2023-6-25 00:30 编辑

要多看几遍

CorrineLL 发表于 2023-7-16 15:56:42

笔记还不更新呀~~~~~~~~~~~~~~~·
页: [1]
查看完整版本: 第068讲:类和对象(XI)