为什么不报错呢?
>>> 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.FishC 的时候,应该报错,对吗?
我认为由于FishC的属性不是C类的属性,所以运行的时候,先调用__getattribute__方法,然后在调用__getattr__
由于FishC属性不存在,所调用__getattribute__方法是,先输出’拿来吧你',然后应该报错才对,我的理解对吗? 你的理解非常接近,但是有一点小小的细节需要补充!让我们一起来跑一趟这段代码,看看它的“背后故事”!
在 Python 中,当你访问一个对象的属性时,会首先调用 `__getattribute__` 方法。这个方法会被调用每一次你试图访问该对象的任何属性,包括那些并不存在的属性。
在你的代码中,当你访问 `c.FishC` 时,会发生以下几个步骤:
1. **调用 `__getattribute__`**:首先,Python 会调用 `C` 类中的 `__getattribute__` 方法。这就是为什么你看到输出的 "拿来吧你~"。
2. **查找属性**:`super().__getattribute__(attrname)` 会寻找 `FishC` 属性。如果它找不到,它会抛出一个 `AttributeError`,但是因为你在 `__getattr__` 方法中定义了行为,Python 会继续到下一步。
3. **调用 `__getattr__`**:由于 `FishC` 并不是 `C` 类的普通属性,Python 接着调用 `__getattr__` 方法。在这里,你检查了 `attrname` 是否等于 "FishC",如果是,你就返回 "I love FishC."。
4. **没有抛出异常**:结果就是你得到了 "I love FishC." 的输出,而不是 `AttributeError`。所以,在这种情况下,没有错误发生,程序平稳运行。
总结一下,虽然 `FishC` 不是 `C` 类的属性,但因为你的 `__getattr__` 中对这个属性做了处理,所以没有报错。倘若你访问一个不存在且不被处理的属性(比如 `c.some_other_attr`),那就会直接抛出 `AttributeError`。
所以,下次当你看到 "拿来吧你~" 时,不要太紧张,Python 只是想告诉你它正在努力找东西呢!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 我想问一下,是不是碰到C类不存在的属性时,
先是调用 `__getattribute__` 方法, 然后调用__getattr__方法
但是 __getattribute__方法中的 super().__getattribute__方法,如果存在__getattr__方法时,是不会调用super().__getattribute__方法的,对吗? wbzxz 发表于 2024-07-30 23:45
我想问一下,是不是碰到C类不存在的属性时,
先是调 ...
是的,您理解得非常好!让我们再稍微详细讲解一下这个过程。
当你访问一个类的属性时,确实是先调用 `__getattribute__` 方法。如果这个属性不存在,流程会继续向下走,最后可能会调用 `__getattr__` 方法。具体步骤如下:
1. **调用 `__getattribute__`**:
- Python 首先尝试通过对象的方法 `__getattribute__` 来获取属性。
- 在您的代码中,这个方法首先打印"拿来吧你~",然后调用 `super().__getattribute__(attrname)` 来查询属性。
2. **查找属性**:
- 如果 `super().__getattribute__(attrname)` 找到这个属性,它就返回这个属性。
- 如果没有找到,会抛出 `AttributeError`。这就是问题所在。
3. **调用 `__getattr__` (如果必要)**:
- 如果在 `__getattribute__` 中没有找到属性并且抛出了 `AttributeError`,这时 Python 会转而调用 `__getattr__` 方法。
- 也就是说,`__getattr__` 只有在 `__getattribute__` 没有找到属性并且抛出异常的情况下才会被触发。
所以,如果你在 `__getattribute__` 中调用了 `super().__getattribute__`,并且找不到该属性,那么它就会抛出 `AttributeError`,而不会进入 `__getattr__`。不过因为你在 `__getattribute__` 的实现中直接处理了返回逻辑(调用了 `super()`),这意味着你可以对属性的访问进行一些定制化的处理。
也就是说, `__getattribute__` 是更基础的属性获取方法,而 `__getattr__` 是一个后备机制,只有在 `__getattribute__` 失败的时候才会被调用。
希望这个解释能帮助您更好地理解它们之间的关系!如果还有不清楚的地方,欢迎继续提问!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 如果你在 `__getattribute__` 中调用了 `super().__getattribute__`,并且找不到该属性,那么它就会抛出 `AttributeError`,当抛出`AttributeError`时,这时候就会去调用__getattr__,根据__getattr__方法所写的代码执行,故不会出现报错问题。
我理解的对吗?
wbzxz 发表于 2024-07-30 23:51
如果你在 `__getattribute__` 中调用了 `super().__ge ...
是的,您理解得非常正确!让我们更清晰地梳理一下这个过程:
1. **调用 `__getattribute__`**:当你尝试访问一个属性时,首先会调用对象的 `__getattribute__` 方法。
2. **查找属性**:
- 在 `__getattribute__` 方法中,如果你使用 `super().__getattribute__(attrname)` 来查找属性,并且该属性不存在,那么 Python 会抛出 `AttributeError`。
- 抛出这个异常后,Python 不会直接终止程序,而是会查找是否有 `__getattr__` 方法来处理这个情况。
3. **调用 `__getattr__`**:
- 如果你的类中定义了 `__getattr__` 方法,Python 将会调用它。
- 在 `__getattr__` 中,你可以根据需要做一些自定义处理,比如返回特定的字符串或者其他对象。
- 如果在 `__getattr__` 中处理完后没有抛出异常(例如,您返回了 "I love FishC."),那么就不会出现报错。
所以,您的总结是完全正确的!通过这种方式,您可以为一些不存在的属性提供备用机制,而不会导致程序运行时抛出错误。这是一种非常灵活的设计,让你能够控制对象对于未知属性的响应。
如果还有疑问或者想了解更多细节,随时欢迎提问!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
[1]