在哪里
Potato.__name__解决?
大多数记录的dunder方法和属性实际上存在于对象的本机代码侧。对于CPython,它们被设置为对象模型中定义的C
Struct中插槽中的指针。(在这里定义-https:
//github.com/python/cpython/blob/04e82934659487ecae76bf4a2db7f92c8dbe0d25/Include/object.h#L346,但是当人们在C中实际创建新类时,字段更容易显示,例如:https:/
/github.com/python/cpython/blob/04e82934659487ecae76bf4a2db7f92c8dbe0d25/Objects/typeobject.c#L7778,其中定义了“超级”类型)
因此,
__name__通过中的代码在那里设置
type.__new__,它是第一个参数。
Potato.__name__=如何处理其他问题(在类定义块的内部和外部)?
类的
__dict__参数不是普通的字典-
它是一个特殊的映射代理对象,其原因恰恰是使得该类本身的所有属性设置都不会通过
__dict__,而是通过
__setattr__type中的方法。在这里,对这些带槽的dunder方法的分配实际上是在C对象的C结构中填充的,然后反映在该
class.__dict__属性上。
因此, 在 类块 之外 ,
cls.__name__以这种方式设置-因为它是在创建类之后发生的。
在 类块内,所有属性和方法都收集到简单的字典中(尽管可以自定义)。该dict传递给了
type.__new__其他元类方法-
但如上所述,即使该方法只是更新了类代理,该方法也会
__name__从显式传递的
name参数(即,传递给的调用中传递的“
name”参数
type.__new__) 填充插槽
__dict__字典中的所有名称都用作名称空间。
这就是为什么
cls.__dict__["__name__"]可以从不同于
cls.__name__插槽中内容的内容开始,但是随后的分配却使两者同步的原因。
一个有趣的轶事是,三天前,我遇到了一些代码,试图
__dict__在类主体中显式地重用该名称,这同样具有令人费解的副作用。我什至想知道是否应该有关于此的错误报告,并询问Python开发人员-
正如我所想到的,权威的答案是:
...all __dunder__ names are reserved for the implementation and they shouldonly be used according to the documentation. So, indeed, it's not illegal,but you are not guaranteed that anything works, either.
(G. van Rossum)
它与尝试
__name__在类主体中定义相同。
https://mail.python.org/pipermail/python-
dev/2018-April/152689.html
而且,如果一个人实际上想重写
__name__为类主体中的一个属性,那么用于该类的元类很简单,因为元类可以是:
class M(type): def __new__(metacls, name, bases, namespace, **kw): name = namespace.get("__name__", name) return super().__new__(metacls, name, bases, namespace, **kw)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)