class test():
name = 'arthur'
def __getattribute__(self, value):
return super().__getattribute__(value)
x = test()
x.name
------------------------------------------
Output: 'arthur'
我正在尝试了解__getattribute__
的潜在机制。我了解(希望如此)在这种情况下,super().__getattribute__(value)
延伸到了对象类。但是object
实际上如何从test()类中获取name
值?如果在避免递归的情况下自己编写在类中,那么如何使用__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
方法/双下划线方法)。这是一个属性/属性访问器方法,即使该属性/属性在类本身中可用,它也会在每个属性/属性访问中进行拦截。另一方面,仅当您要访问的属性在类/实例中不存在时才调用__getattr__
magic方法。无论如何...
还有另一件事要注意,正如您可能已经知道的那样,所有类都隐式或显式扩展/继承了基类object
。因此,您定义的任何类,默认的父类都是内置的object
类。您被问到感到困惑:
我(希望)理解
super().__getattribute__(value)
达到了在这种情况下转到object
类。但是object
实际如何从name
类中提取test()
值?
因此,让我们先看一些基本示例:
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)
您正在将上下文(类的实例)显式传递给父类(object
)。因此父/对象类知道上下文并从该传递的实例中获取属性。另一方面,当您致电:
super().__getattribute__(name)
Python为您设置上下文。因此,您可以想象这样的事情:
super(test, self).__getattribute__(name) # it's valid
但是在这种情况下,它是隐式的,这是super()
调用知道在哪里查找属性的方式。值得一提的是,Python的super()
内置函数返回一个代理object,该代理可以通过委派调用基类的方法,并且super()
可以接受两个参数(如您在上一代码中所看到的)片段),第一个是子类类型(在这种情况下为test
),第二个参数是一个对象,即该子类的实例(test
)。
在Python 3
中,super(test, self)
调用等效于无参数的super()
调用。希望我能澄清您的困惑。您可以阅读有关super()的更多信息。