__get__,__getattr__和__getattribute都是访问属性的方法,但不太相同。
object.__getattr__(self, name)
当一般位置找不到attribute的时候,会调用getattr,返回一个值或AttributeError异常。
object.__getattribute__(self, name)
无条件被调用,通过实例访问属性。如果class中定义了__getattr__(),则__getattr__()不会被调用(除非显示调用或引发AttributeError异常)
object.__get__(self, instance, owner)
如果class定义了它,则这个class就可以称为descriptor。owner是所有者的类,instance是访问descriptor的实例,如果不是通过实例访问,而是通过类访问的话,instance则为None。(descriptor的实例自己访问自己是不会触发__get__,而会触发__call__,只有descriptor作为其它类的属性才有意义。)(所以下文的d是作为C2的一个属性被调用)
class C(object):
a = 'abc'
def __getattribute__(self, *args, **kwargs):
print("__getattribute__() is called")
return object.__getattribute__(self, *args, **kwargs)
# return "haha"
def __getattr__(self, name):
print("__getattr__() is called ")
return name + " from getattr"
def __get__(self, instance, owner):
print("__get__() is called", instance, owner)
return self
def foo(self, x):
print(x)
class C2(object):
d = C()
if __name__ == '__main__':
c = C()
c2 = C2()
print(c.a)
print(c.zzzzzzzz)
c2.d
print(c2.d.a)
输出结果是:
__getattribute__() is called
abc
__getattribute__() is called
__getattr__() is called
zzzzzzzz from getattr
__get__() is called <__main__.C2 object at 0x16d2310> <class '__main__.C2'>
__get__() is called <__main__.C2 object at 0x16d2310> <class '__main__.C2'>
__getattribute__() is called
abc
小结:可以看出,每次通过
实例访问属性,都会经过__getattribute__函数。而当属性不存在时,仍然需要访问__getattribute__,不过接着要访问__getattr__。这就好像是一个异常处理函数。
每次访问descriptor(即实现了__get__的类),都会先经过__get__函数。
需要注意的是,当使用类访问不存在的变量是,不会经过__getattr__函数。而descriptor不存在此问题,只是把instance标识为none而已。
分享到:
相关推荐
### 详解 Python 中 `__get__` 和 `__getattr__` 与 `__getattribute__` 的区别 在 Python 编程语言中,对象的属性访问机制是非常灵活且强大的。当我们试图通过点号(`.`)操作符去访问一个对象的属性时,Python 会...
在Python中,`__getattr__` 和 `__getattribute__` 都是用来处理对象属性访问的特殊方法,但它们在何时以及如何被调用上有显著的区别。了解这些区别对于编写更灵活、更具动态特性的代码至关重要。 首先,`__getattr...
在Python编程语言中,有一些特殊的内置方法被称为“魔法函数”(Magic Methods),它们通常以两个下划线开头和结尾,例如`__getattr__`和`__getattribute__`。这两个魔法函数都涉及到对象属性的访问,但它们在处理不...
class Book(object): def __setattr__(self, name, value): if name == ‘value’: object.__setattr__(self, name, value – 100) else: object.__setattr__(self, name, value) def __getattr__(self, name)...
本文将深入探讨Python中几种属性访问方式的区别和用法,包括常规的点号访问、特殊方法`__getattr__`、`__getattribute__`、`__get__`以及`__getitem__`。 1. 常规属性访问: 当我们使用点号`.`来访问一个对象的...
在Python编程语言中,特殊函数(也称为魔术方法或双下划线方法)提供了一种机制,使开发人员能够为自定义类实现特定的行为。这些特殊函数通常以双下划线(`__`)开头并以双下划线结束,如`__init__`、`__str__`等。...
- **`__getattribute__()`**:访问任何属性时都会被调用,如果同时定义了 `__getattr__`,那么只有当 `__getattribute__` 抛出 `AttributeError` 异常时,才会调用 `__getattr__`。 - **`__get__()`** 和 **`__set__...
1.8 属性相关:`__getattr__`、`__setattr__`、`__getattribute__`、`__dir__`,分别用于获取不存在的属性、设置属性、获取属性(会先调用`__getattribute__`),以及返回对象的属性目录。 1.9 属性描述符:`__get_...
在Python编程语言中,反射和描述器是两个重要的特性,它们提供了高级的元编程能力,使得程序员可以在运行时动态地检查、操作甚至修改对象的行为。本文将深入探讨这两个概念及其在Python中的应用。 首先,反射是指...
Descriptors(描述符)是Python语言中一个深奥但很重要的一个黑魔法,它被广泛应用于Python语言的内核,熟练掌握描述符将会为Python程序员的工具箱添加一个额外的技巧。本文我将讲述描述符的定义以及一些常见的场景,...
- 改进了`__getattr__`和`__getattribute__`方法的行为,使其更加一致和明确。 - `f-string`改进:现在可以包含表达式,如`f"{x if condition else y}"`。 安装`python-3.9.2-amd64.exe`程序会为你的系统添加...
3. **反射与动态编程**:了解`__getattr__`, `__getattribute__`等方法,以及`inspect`模块的使用。 通过阅读和实践《Python3 Cookbook最新版》中的内容,开发者可以深化对Python语言的理解,提高编程效率,写出更...
在Python编程语言中,私有属性(private attributes)是一种封装机制,主要用于限制对象内部状态的直接访问,以防止外部代码不恰当的修改。通常,我们通过在变量名前加两个下划线`__`来声明一个私有属性,例如`__...
- `__getattr__(self, name)`: 当尝试访问一个不存在的属性时,Python会调用此方法。可以在这里定义默认行为,如返回一个默认值或抛出异常。 - `__getattribute__(self, name)`: 对象的任何属性访问都会触发此...
这两种类在Python的不同版本中有着显著的区别,特别是在处理多继承、属性访问和元类(metaclass)方面。新式类是自Python 2.2版本引入的概念,其主要目的是为了解决经典类的一些问题,并引入了一些新的特性。 首先...
在Python中,`__init__` 和 `__new__` 方法对于类的实例化过程至关重要。 - **`__init__` 方法**:主要用于初始化一个新实例。它是在类实例被创建之后立即调用的方法,负责完成初始化过程。由于 `__init__` 是实例...