首页 > 解决方案 > 如何使用其文档字符串文档获取 Python 类的变量列表

问题描述

如何从 Python 类或数据类中获取类成员变量及其文档字符串描述的列表?

我有这个数据类

@dataclass
class MyDataClass(BaseDataClass):
    """
    :param var1: Description for var1
    :param var2: Description for var2
    """
    var1: int
    var2: int

我希望能够为此获取此信息:

{
  'var1': ('int', 'Description for var1'), 
  'var2': ('int', 'Description for var2')
}

标签: python-3.xclassintrospection

解决方案


为了获得类成员变量的列表及其描述,我使用 classmethod 创建了一个空数据类

get_user_parameters_dict(cls)

它解析类文档字符串并返回包含成员名称、类型和描述的管道。由于文档字符串不是自动生成的,因此您需要按照以下代码中的示例进行操作。主要部分的输出是

输出:

This does not work for a class without properties
This class is probably BaseDataClass. Is it? Actual name: BaseDataClass

var1: int - Description for var1
var2: int - Description for var2


from dataclasses import dataclass
from typing import Dict, Tuple
import re

代码:

@dataclass
class BaseDataClass:
    """
    Example of how to docstring var1 and var2, so reflection works here
    :param var1: Description for var1
    :param var2: Description for var2
    """

    # Example of declaring properties var1 and var2
    # var1: int
    # var2: int

    @classmethod
    def get_user_parameters_dict(cls) -> Dict[str, Tuple[str, str]]:
        properties_descriptions: Dict[str, str] = {}
        regex = r":param *(.*): *(.*)"
        from typing import Generator
        matches: Generator[re.Match, None, None] = re.finditer(regex, cls.__doc__, re.MULTILINE)
        for match in matches:
            prop_name: str = match.groups()[0]
            prop_description: str = match.groups()[1]
            properties_descriptions[prop_name] = prop_description

        dataclass_properties: Dict[str, Tuple[str, str]] = {}
        try:
            dataclass_annotations: Dict[str, object] = cls.__dict__['__annotations__']
            for prop_name, property_type in dataclass_annotations.items():
                dataclass_properties[prop_name] = (property_type.__name__, properties_descriptions[prop_name])

            return dataclass_properties
        except KeyError as ke:
            print('This does not work for a class without properties')



@dataclass
class MyDataClass(BaseDataClass):
    """
    :param var1: Description for var1
    :param var2: Description for var2
    """
    var1: int
    var2: int


if __name__ == '__main__':
    a = BaseDataClass
    try:
        for property_name, property_metadata in BaseDataClass.get_user_parameters_dict().items():
            print(f'{property_name}: {property_metadata[0]} - {property_metadata[1]}')
    except AttributeError as ae:
        print(f'This class is probably TestuserProperties. Is it? Actual name: {BaseDataClass.__name__}')

    print()

    for property_name, property_metadata in MyDataClass.get_user_parameters_dict().items():
        print(f'{property_name}: {property_metadata[0]} - {property_metadata[1]}')

推荐阅读