__getattribute__ 如何取值?
How does __getattribute__ fetch a value?
class test():
name = 'arthur'
def __getattribute__(self, value):
return super().__getattribute__(value)
x = test()
x.name
------------------------------------------
Output: 'arthur'
我正在尝试了解 __getattribute__
的基本机制。我理解(希望如此)在这种情况下 super().__getattribute__(value)
会接触到对象 class。但是 object
实际上是如何从 test() class 中获取 name
值的呢?如果在避免递归的情况下自己在 class 中编码,如何使用 __getattribute__
获取属性值?
正如我所说,我想了解底层机制,我知道这不是您通常处理事情的方式。
谢谢!
您不能在 Python 中编写此代码。这是 Python 调用的 C 函数:
PyObject *
PyObject_GetAttr(PyObject *v, PyObject *name)
{
PyTypeObject *tp = Py_TYPE(v);
if (!PyUnicode_Check(name)) {
PyErr_Format(PyExc_TypeError,
"attribute name must be string, not '%.200s'",
name->ob_type->tp_name);
return NULL;
}
if (tp->tp_getattro != NULL)
return (*tp->tp_getattro)(v, name);
if (tp->tp_getattr != NULL) {
const char *name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL)
return NULL;
return (*tp->tp_getattr)(v, (char *)name_str);
}
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%U'",
tp->tp_name, name);
return NULL;
}
这是object.__getattribute__
。在您的示例中调用它是因为所有 类 都继承自 object
.
首先,__getattribute__
是一个神奇的方法(又名 dunder
method/double 下划线方法)。这是一个 property/attribute 访问器方法,它会在每次 property/attribute 访问时进行拦截,即使 property/attribute 在 class 本身中可用也是如此。另一方面,仅当您访问的 属性 不存在于 class/instance 中时,才会调用 __getattr__
魔法方法。无论如何...
还有一件更重要的事情需要注意,正如您可能已经知道的那样,所有 class 都是 extends/inherits 基数 object
class 隐式或显式.所以,任何你定义的 class,默认父 class 是内置的 object
class。你一问就糊涂了:
I understand (hopefully) that super().__getattribute__(value)
reaches
out to the object
class in this case. But how actually does object
fetch the name
value out of the test()
class?
所以让我们先看一些基本的例子:
class Foo:
def __init__(self, name):
self.name = name
def __getattribute__(self, name):
return super().__getattribute__(name)
等同于
class Foo(object):
def __init__(self, name):
self.name = name
def __getattribute__(self, name):
return object.__getattribute__(self, name)
所以,当你打电话给
object.__getattribute__(self, name)
您正在将上下文(class 的实例)显式传递给父级 (object
) class。所以 parent/object class 知道上下文并从传递的实例中获取属性。另一方面,当你打电话时:
super().__getattribute__(name)
Python 为您设置上下文。所以,你可以想象这样的事情:
super(test, self).__getattribute__(name) # it's valid
但在这种情况下,它是隐式的,这就是 super()
调用知道在哪里查找属性的方式。值得一提的是,Python的super()
内置函数returns一个代理object,一个替代对象,可以通过委托调用基class的方法而且 super()
可以带两个参数(正如您在前面的代码片段中看到的),第一个是 subclass 类型(在本例中是 test
),第二个参数是一个对象,该子对象的一个实例class (test
).
在Python 3
中,super(test, self)
调用等同于无参数super()
调用。希望我已经澄清了你的困惑。您可以阅读更多关于 super().
class test():
name = 'arthur'
def __getattribute__(self, value):
return super().__getattribute__(value)
x = test()
x.name
------------------------------------------
Output: 'arthur'
我正在尝试了解 __getattribute__
的基本机制。我理解(希望如此)在这种情况下 super().__getattribute__(value)
会接触到对象 class。但是 object
实际上是如何从 test() class 中获取 name
值的呢?如果在避免递归的情况下自己在 class 中编码,如何使用 __getattribute__
获取属性值?
正如我所说,我想了解底层机制,我知道这不是您通常处理事情的方式。
谢谢!
您不能在 Python 中编写此代码。这是 Python 调用的 C 函数:
PyObject *
PyObject_GetAttr(PyObject *v, PyObject *name)
{
PyTypeObject *tp = Py_TYPE(v);
if (!PyUnicode_Check(name)) {
PyErr_Format(PyExc_TypeError,
"attribute name must be string, not '%.200s'",
name->ob_type->tp_name);
return NULL;
}
if (tp->tp_getattro != NULL)
return (*tp->tp_getattro)(v, name);
if (tp->tp_getattr != NULL) {
const char *name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL)
return NULL;
return (*tp->tp_getattr)(v, (char *)name_str);
}
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%U'",
tp->tp_name, name);
return NULL;
}
这是object.__getattribute__
。在您的示例中调用它是因为所有 类 都继承自 object
.
首先,__getattribute__
是一个神奇的方法(又名 dunder
method/double 下划线方法)。这是一个 property/attribute 访问器方法,它会在每次 property/attribute 访问时进行拦截,即使 property/attribute 在 class 本身中可用也是如此。另一方面,仅当您访问的 属性 不存在于 class/instance 中时,才会调用 __getattr__
魔法方法。无论如何...
还有一件更重要的事情需要注意,正如您可能已经知道的那样,所有 class 都是 extends/inherits 基数 object
class 隐式或显式.所以,任何你定义的 class,默认父 class 是内置的 object
class。你一问就糊涂了:
I understand (hopefully) that
super().__getattribute__(value)
reaches out to theobject
class in this case. But how actually doesobject
fetch thename
value out of thetest()
class?
所以让我们先看一些基本的例子:
class Foo:
def __init__(self, name):
self.name = name
def __getattribute__(self, name):
return super().__getattribute__(name)
等同于
class Foo(object):
def __init__(self, name):
self.name = name
def __getattribute__(self, name):
return object.__getattribute__(self, name)
所以,当你打电话给
object.__getattribute__(self, name)
您正在将上下文(class 的实例)显式传递给父级 (object
) class。所以 parent/object class 知道上下文并从传递的实例中获取属性。另一方面,当你打电话时:
super().__getattribute__(name)
Python 为您设置上下文。所以,你可以想象这样的事情:
super(test, self).__getattribute__(name) # it's valid
但在这种情况下,它是隐式的,这就是 super()
调用知道在哪里查找属性的方式。值得一提的是,Python的super()
内置函数returns一个代理object,一个替代对象,可以通过委托调用基class的方法而且 super()
可以带两个参数(正如您在前面的代码片段中看到的),第一个是 subclass 类型(在本例中是 test
),第二个参数是一个对象,该子对象的一个实例class (test
).
在Python 3
中,super(test, self)
调用等同于无参数super()
调用。希望我已经澄清了你的困惑。您可以阅读更多关于 super().