- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
>>> class D:
... __class__ = 1
... __name__ = 2
...
>>> D.__class__
<class 'type'>
>>> D().__class__
1
>>> D.__name__
'D'
>>> D().__name__
2
为什么D.__class__
返回类名,而D().__class__
返回类D中定义的属性?
__class__
和 __name__
等内置属性从何而来?
我怀疑 __name__
或 __class__
是存在于 object
类或某处的简单描述符,但这看不到。
在我的理解中,Python中的属性查找规则如下,省略了描述符等条件..:
Instance --> Class --> Class.__bases__ 以及其他类的基础
鉴于类是元类的实例,在这种情况下,type
为什么 D.__class__
不查找 __class__
D.__dict__
中的?
最佳答案
名字__class__
和 __name__
很特别。两者都是数据描述符。 __name__
在 type
上定义对象,__class__
在 object
上定义(所有新型类的基类):
>>> type.__dict__['__name__']
<attribute '__name__' of 'type' objects>
>>> type.__dict__['__name__'].__get__
<method-wrapper '__get__' of getset_descriptor object at 0x1059ea870>
>>> type.__dict__['__name__'].__set__
<method-wrapper '__set__' of getset_descriptor object at 0x1059ea870>
>>> object.__dict__['__class__']
<attribute '__class__' of 'object' objects>
>>> object.__dict__['__class__'].__get__
<method-wrapper '__get__' of getset_descriptor object at 0x1059ea2d0>
>>> object.__dict__['__class__'].__set__
<method-wrapper '__set__' of getset_descriptor object at 0x1059ea2d0>
因为它们是数据描述符,所以 type.__getattribute__
method (用于类的属性访问)将忽略类中设置的任何属性 __dict__
并且只使用描述符本身:
>>> type.__getattribute__(Foo, '__class__')
<class 'type'>
>>> type.__getattribute__(Foo, '__name__')
'Foo'
有趣的事实:type
源自 object
(Python 中的一切 都是对象)这就是为什么 __class__
在 type
上找到检查数据描述符时:
>>> type.__mro__
(<class 'type'>, <class 'object'>)
( type.__getattribute__(D, ...)
直接用作未绑定(bind)方法,而不是 D.__getattribute__()
,因为 all special method access goes to the type )。
参见 Descriptor Howto什么是数据描述符及其重要性:
If an object defines both
__get__()
and__set__()
, it is considered a data descriptor. Descriptors that only define__get__()
are called non-data descriptors (they are typically used for methods but other uses are possible).Data and non-data descriptors differ in how overrides are calculated with respect to entries in an instance’s dictionary. If an instance’s dictionary has an entry with the same name as a data descriptor, the data descriptor takes precedence. If an instance’s dictionary has an entry with the same name as a non-data descriptor, the dictionary entry takes precedence.
对于 type
上的数据描述符,一个类只是另一个实例。
所以在查找 __class__
时或 __name__
属性,在 D.__dict__
中定义什么并不重要命名空间,因为在 type
形成的命名空间中可以找到数据描述符这是 MRO。
这些描述符在 typeobject.c
C code 中定义:
static PyGetSetDef type_getsets[] = {
{"__name__", (getter)type_name, (setter)type_set_name, NULL},
/* ... several more ... */
}
/* ... */
PyTypeObject PyType_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"type", /* tp_name */
/* ... many type definition entries ... */
type_getsets, /* tp_getset */
/* ... many type definition entries ... */
}
/* ... */
static PyGetSetDef object_getsets[] = {
{"__class__", object_get_class, object_set_class,
PyDoc_STR("the object's class")},
{0}
};
PyTypeObject PyBaseObject_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"object", /* tp_name */
/* ... many type definition entries ... */
object_getsets, /* tp_getset */
/* ... many type definition entries ... */
}
在实例上,object.__getattribute__
被使用,它会找到 __name__
和 __class__
D.__dict__
中的条目在它找到 object
上的数据描述符之前进行映射或 type
.
但是,如果您省略其中任何一个,则在 D()
上查找名称只会__class__
作为 D
的 MRO 中的数据描述符(所以,在 object
上)。 __name__
未找到,因为解析实例属性时未考虑元类型。
因此你可以设置__name__
在一个实例上,但不是 __class__
:
>>> class E: pass
...
>>> e = E()
>>> e.__class__
<class '__main__.E'>
>>> e.__name__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'E' object has no attribute '__name__'
>>> e.__dict__['__class__'] = 'ignored'
>>> e.__class__
<class '__main__.E'>
>>> e.__name__ = 'this just works'
>>> e.__name__
'this just works'
关于python - 类属性查找规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39169600/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!