python 中的 dict 和 attrs 是什么关系?

What's relationship between dict and attrs in python?

我是 python 的初学者。我正在学习 meta-class 但我不太了解字典如何存储方法和属性?

class ModelMetaclass(type):
    def __new__(cls, name, bases, attrs):
        if name=='Model':
            return type.__new__(cls, name, bases, attrs)
        print('Found model: %s' % name)
        mappings = dict()
        for k, v in attrs.items():
            if isinstance(v, Field):
                print('Found mapping: %s ==> %s' % (k, v))
                mappings[k] = v
        for k in mappings.keys():
            attrs.pop(k)
        attrs['__mappings__'] = mappings
        attrs['__table__'] = name 
        return type.__new__(cls, name, bases, attrs)

我假设 attrs 不仅可以存储变量,还可以存储方法。如果是这样的话,这本字典中的键和值是什么,attrs?

class 的所有属性确实存储在字典中。请注意,方法 也只是属性 ;他们恰好是可调用的。 Python 在很多地方使用字典;例如,模块的全局名称空间也是一个字典。 object.__getattribute__ hook 的工作通常是将属性访问转换为属性字典中的键查找。

class 语句的主体像函数一样执行,然后将生成的本地命名空间(通过调用 locals() 生成的字典)交给 metaclass 以生成class 对象。这就是 attrs 在您的示例代码中绑定的内容。

参见 class statement reference documentation:

The class’s suite is then executed in a new execution frame (see [Naming and binding](The class’s suite is then executed in a new execution frame (see Naming and binding), using a newly created local namespace and the original global namespace. (Usually, the suite contains mostly function definitions.) When the class’s suite finishes execution, its execution frame is discarded but its local namespace is saved. A class object is then created using the inheritance list for the base classes and the saved local namespace for the attribute dictionary.

大胆强调我的。

您可以在 Metaclasses section of the datamodel documentation; quoting the Creating the class object section 中找到更多详细信息:

Once the class namespace has been populated by executing the class body, the class object is created by calling metaclass(name, bases, namespace, **kwds)

命名空间字典随后由 type.__new__() 附加到新创建的 class 对象。

datamodel documentation 也涵盖了这一点,在 自定义 classes 部分下:

A class has a namespace implemented by a dictionary object. Class attribute references are translated to lookups in this dictionary, e.g., C.x is translated to C.__dict__["x"] (although there are a number of hooks which allow for other means of locating attributes).

您可能还想阅读 descriptors;方法是通过将 class 命名空间中找到的函数绑定到您在其上查找方法名称的实例来创建的。