laocaiye 发表于 2025-11-6 19:48:14

关于第068讲:类和对象(XI)的例题

下面一段代码是该课程视频中的例子

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.x
执行结果是:
        拿来吧你~
        Traceback (most recent call last):
       File "<pyshell#5>", line 1, in <module>
              c.x
        File "<pyshell#1>", line 12, in __getattr__
            raise AttributeError(attrname)
        拿来吧你~
        拿来吧你~
        AttributeError: x

为何会出现3次“拿来吧你~”,下面两次怎么回事?

FishC 发表于 2025-11-6 19:52:45

在您的代码中,当执行 `c.x` 时,出现了三次“拿来吧你~”的输出。这是因为在属性访问和异常处理过程中,多次触发了 `__getattribute__` 方法。下面逐步解释原因:

1. 第一次“拿来吧你~”:当执行 `c.x` 时,直接触发 `__getattribute__('x')` 方法,打印第一次“拿来吧你~”。然后,`super().__getattribute__('x')` 尝试获取属性 `x`,但 `x` 不存在,因此抛出 `AttributeError`。

2. 第二次“拿来吧你~”:由于 `__getattribute__` 抛出了 `AttributeError`,Python 会尝试调用 `__getattr__` 方法。但调用 `c.__getattr__('x')` 本身也是一次属性访问(获取 `__getattr__` 方法),因此再次触发 `__getattribute__('__getattr__')`,打印第二次“拿来吧你~”。

3. 第三次“拿来吧你~”:在 `__getattr__` 方法中,执行 `raise AttributeError(attrname)` 抛出异常。在异常处理过程中(例如打印 Traceback 时),Python 可能会访问实例 `c` 的属性(如 `__class__` 用于对象表示),从而第三次触发 `__getattribute__`,打印第三次“拿来吧你~”。

总结:三次打印分别对应:
- 第一次:直接访问 `c.x`
- 第二次:获取 `__getattr__` 方法
- 第三次:异常处理中的属性访问

这是 Python 属性访问机制和异常处理交互的正常行为。如果您想避免多次触发,可以谨慎设计 `__getattribute__` 方法。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 关于第068讲:类和对象(XI)的例题