九歌当下 发表于 2023-8-29 15:19:45

类中使用__getattribute__魔法方法后在实例化对象中访问不存在的属性会打印3次

class C:
    def __init__(self, name, age):
      self.name = name
      self.__age = age
    def __getattribute__(self, attrname):
      print("拿来吧你")
      return super().__getattribute__(attrname)
定义类C

c = C("九歌当下",18)
c.name
拿来吧你
'九歌当下'
c._C__age
拿来吧你
18
c.fishC
拿来吧你
Traceback (most recent call last):
File "<pyshell#33>", line 1, in <module>
    c.fishC
File "<pyshell#28>", line 7, in __getattribute__
    return super().__getattribute__(attrname)
拿来吧你
拿来吧你
AttributeError: 'C' object has no attribute 'fishC'

创建实例化对象小c后,访问不存在的属性fsih后,为什么会打印三次"拿来吧你"?{:10_266:}

isdkz 发表于 2023-8-29 17:45:28


在Python中,当你尝试访问一个对象的属性时,Python会首先调用`__getattribute__`方法。如果该属性不存在,Python会抛出`AttributeError`异常。然后,Python会尝试调用`__getattr__`方法。如果`__getattr__`方法也不存在,Python会再次抛出`AttributeError`异常。

在你的代码中,你重写了`__getattribute__`方法,并在其中添加了打印语句。因此,每次尝试访问属性时,无论该属性是否存在,都会打印一次"拿来吧你"。

然而,当你尝试访问不存在的属性`fishC`时,`super().__getattribute__(attrname)`会抛出`AttributeError`异常。这会导致Python尝试调用`__getattr__`方法。但是,因为你没有定义`__getattr__`方法,Python会再次调用`__getattribute__`方法,再次打印"拿来吧你",然后再次抛出`AttributeError`异常。这就是为什么会打印三次"拿来吧你"的原因。

如果你不希望在访问不存在的属性时打印三次"拿来吧你",你可以在`__getattribute__`方法中捕获`AttributeError`异常,如下所示:

class C:
    def __init__(self, name, age):
      self.name = name
      self.__age = age
    def __getattribute__(self, attrname):
      print("拿来吧你")
      try:
            return super().__getattribute__(attrname)
      except AttributeError:
            pass# 或者你可以在这里处理异常,例如返回一个默认值


这样,当你尝试访问不存在的属性时,只会打印一次"拿来吧你"。

或者定义 __getattr__ 方法:
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):
      pass

kevin_zxy 发表于 2023-11-7 21:00:45

{:10_266:}

captian 发表于 2023-12-14 21:36:47

为什么访问不存在的属性`fishC`时,`super().__getattribute__(attrname)`会抛出`AttributeError`异常呢?抛出异常的话,代码执行不应该中断吗?怎么还会继续执行代码呢?
页: [1]
查看完整版本: 类中使用__getattribute__魔法方法后在实例化对象中访问不存在的属性会打印3次