小能豆

__getattr__ 和 __getattribute__ 之间的区别

javascript

我想了解何时定义__getattr__或__getattribute__。python文档中提到的__getattribute__适用于新式类。什么是新式类?


阅读 41

收藏
2024-08-28

共1个答案

小能豆

在 Python 中,”新式类”(new-style classes)是 Python 2.2 引入的一种类类型,与”经典类”(classic classes)相对。所有在 Python 3 中定义的类默认都是新式类,而在 Python 2 中,只有显式继承自 object 的类才是新式类。

经典类 vs. 新式类

  • 经典类(Classic Classes):在 Python 2 中,未继承自 object 的类。例如:
    python class MyClass: pass
    这种定义方式在 Python 2 中会创建一个经典类。

  • 新式类(New-Style Classes):在 Python 2 中,继承自 object 的类,或者在 Python 3 中定义的所有类。例如:
    python class MyClass(object): pass
    这种定义方式在 Python 2 中会创建一个新式类,而在 Python 3 中,无论是否继承 object,所有类都是新式类。

为什么使用新式类?

新式类引入了多个改进和特性,使得 Python 的面向对象编程模型更为一致和强大,例如:

  • 统一的类型系统:在新式类中,所有类型(包括内建类型和用户定义的类型)都是 object 的子类。
  • 方法解析顺序(MRO):新式类使用 C3 线性化算法确定多重继承中的方法解析顺序,这比经典类中的深度优先搜索更合理。
  • 更多内置魔术方法:如 __getattribute____new__super() 的改进等。

__getattr____getattribute__ 的区别

  • __getattr__:当访问一个不存在的属性时才会调用这个方法。如果试图访问的属性在实例或类中不存在,那么 __getattr__ 会被调用。
  • __getattribute__:每次访问对象的任何属性时都会调用这个方法。由于 __getattribute__ 在属性访问时总是被调用,因此如果使用它时不小心处理,可能会导致无限递归。

什么时候定义 __getattr____getattribute__

  • 定义 __getattr__:通常在你希望动态处理或默认处理未定义的属性时使用。例如,如果你想要提供一些默认行为或在属性不存在时执行特定的逻辑,定义 __getattr__ 是合适的。

  • 定义 __getattribute__:如果你需要截获并自定义对象的属性访问(包括已存在的属性),你可以定义 __getattribute__。但是,由于它在每次访问属性时都会被调用,因此要特别注意避免递归问题。

简而言之,Python 3 中所有类都是新式类,所以你可以直接使用 __getattribute____getattr__,无需担心兼容性问题。如果你还在使用 Python 2,记得继承 object 以确保你的类是新式类。

2024-08-28