跳至內容

用戶: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)