跳转到内容

User:Xyy23330121/Python/特殊属性

来自维基学院


Python 有一些特殊属性,这些特殊属性在使用 Python 创建各种内容时自动生成的。比如:

import math
print(math.__name__) #输出:math


a = 1
print(a.__class__)   #输出:<class 'int'>

本章将记录这些特殊属性。

特殊属性与方法列表
属性名称 属性说明 是否
只读
适用范围
实例 实例
方法
函数 模块 生成器
实例
__name__ 默认为创建该对象时使用的名称。参见name
__qualname__ 创建该对象时的 限定名称
__module__ 定义该对象时使用的模块名称。
__doc__ 文档字符串
如果未设置文档字符串,此项为 None
__annotations__ 类型注释信息
本行为使用 obj.__annotations__ 方法获取的 __annotations__ 属性。
__annotations__ 使用 inspect.get_annotations 获取的 __annotations__ 属性。
__type_params__ 泛型函数与泛型类 的类型注释信息。
__dict__ 存储对象属性的字典。参见:详细说明。。
__static_attributes__ 类或实例各属性名称构成的元组。
__bases__ 类的父类型构成的元组。参见:类的继承
__mro__ 用于处理类继承行为的属性。参见:类的继承
__class__ 类实例所属的类型

详细说明

[编辑 | 编辑源代码]

__name__ 属性并非只读属性。对于上表中任意默认不支持 __name__ 属性的,我们总可以自己设置 __name__ 属性的内容,从而使它可用。

在使用描述器时,有些描述器会自动设置自己的 __name__ 属性,从而使 __name__ 属性可用。

from functools import cached_property

class cls:
    '''doc'''
    
    @property
    def property_attr(self):  # __name__可用
        return 0
    
    @cached_property
    def other_described_attr(self):  # __name__ 不可用
        return 0
        
    @cached_property
    def another_described_attr(self):
        return 0
    another_described_attr.__name__ = "another_described_attr"  # __name__ 可用

在实现描述器时,可以加入以下的方法,从而实现 __name__ 属性的自动设置。

class cls:
    def __get__(self, instance, owner = None): ...
    def __set_name__(self, owner, name):
        self.__name__ = name

__qualname__ 属性和 __name__ 属性是类似的。但该属性还保存了该对象的路径,比如:

可以看出,__qualname__ 完整地保存了对象的路径,而 __name__ 只保存了对象的名称。

class A:
    class B:
        def c(self): pass

obj = A()
print(obj.B.c.__name__)      #输出:c
print(obj.B.c.__qualname__)  #输出:A.B.c

存储对象属性的字典。对于存在 __dict__ 属性的对象,以下行为是等价的:

obj.attr = value
obj.__dict__["attr"] = value

一部分对象(比如许多Python内置对象)不存在这一属性,而是使用 __slot__ 属性。__slot__ 属性相比使用 __dict__ 可以显著节省空间,属性查找速度也可得到显著的提升,但在使用上具有一些限制。参见:

读者可能发现 __class__ 属性对所有对象都有用。实际上:

  • 类是 <class 'type'> 的实例
  • 实例方法是 <class 'method'> 的实例
  • 函数和生成器是 <class 'function'> 的实例
  • 模块是 <class 'module'> 的实例

inspect 模块

[编辑 | 编辑源代码]

除上面列出的特殊属性之外,inspect 模块列出了所有可获得的内置特殊属性。详情请参见 Python 文档。

测试属性是否可用时使用的代码

[编辑 | 编辑源代码]
from functools import cached_property

class cls:
    '''doc'''
    def method(self): pass

    attr = 0

    @property
    def property_attr(self):
        return 0
    
    @cached_property
    def other_described_attr(self):
        return 0

def func():
    '''doc'''
    pass

def generator():
    '''doc'''
    yield 0

instance = cls()

import fractions as module

types = {
    "类": cls, 
    "实例": instance, 
    "实例<br />方法": instance.method, 
    # "实例<br />属性": instance.attr,
    "函数": func, 
    "模块": module, 
    "生成器<br />实例": generator,
    # "描述器<br />实例": cls.property_attr, 
    # "描述器<br />实例2": cls.other_described_attr, 
    # "描述器<br />实例3": instance.property_attr, 
    # "描述器<br />实例4": instance.other_described_attr
}

def test_attr(attrname, get_attr = None):
    print("|-\n!", attrname)
    print("| 默认说明")
    print("| ")
    if get_attr is None: get_attr = getattr
    for item in types:
        try:
            attr = get_attr(types[item], attrname)
            print("| style = \"background-color:#6F6\" | ")
            #print(attr)
        except Exception as e:
            print("| style = \"background-color:#E44\" | ")

if __name__ == "__main__":
    print("|-\n! "+"\n! ".join(types.keys()))
    from inspect import get_annotations as getanno
    get_annotations = lambda item, attrname: getanno(item)
    attrs = (
        "__name__", 
        "__qualname__",
        "__module__",
        "__doc__",
        "__annotations__",
        ("__annotations__", get_annotations),
        "__type_params__",
        "__dict__",
        "__static_attributes__",
        "__bases__",
        "__mro__",
        "__class__"
        )
    for attr in attrs:
        if isinstance(attr, str):
            test_attr(attr)
        else:
            test_attr(*attr)