__ getattribute__如何获取值?

问题描述 投票:2回答:2
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-3.x function class built-in
2个回答
0
投票

您无法使用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;
}

https://github.com/python/cpython/blob/8289e27393395ee903bd096d42e07c112d7f15c6/Objects/object.c#L1001-L1024

这是object.__getattribute__。在您的示例中称为,因为所有类都继承自object


0
投票

首先,__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()的更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.