如何获取Python 3中属于特定类的所有属性(继承的属性除外)的值

问题描述 投票:0回答:2

如何(在 Python 3 中)获取属于特定类的所有属性的值。我只需要那些在特定类中定义的值(属性),而不需要继承的值。

这是一些例子:

class A(object):
    def __init__(self, color):
        self._color = color

    @property
    def color(self):
        return self._color

class B(A):
    def __init__(self, color, height, width):
        super().__init__(color)
        self._height = height
        self._width = width

    @property
    def height(self):
        return self._height

    @property
    def width(self):
        return self._width

这是获取所有值(包括继承的值)的代码:

b_inst = B('red', 10, 20)
val = [{p: b_inst.__getattribute__(p)} for p in dir(B)
       if isinstance(getattr(B, p), property)]

print(val)

>> [{'color': 'red'}, {'height': 10}, {'width': 20}]

现在,我只想检索仅在

class B
中定义的属性值,即
height
width

python python-3.x oop inheritance properties
2个回答
1
投票

请注意,在 Python 中,“属性”具有非常具体的含义(内置

property
类型)。如果您只关心这一点,那么您只需查找您孩子班级的
__dict__

val = [p.__get__(c) for k, p in type(c).__dict__.items() if isinstance(p, property)]

如果你想要对任何任意属性起作用的东西,那么你所要求的就是不可能的,因为Python对象(有一些例外)是基于字典的(与C ++或Java中基于结构的)和动态的(任何片段)代码可以在每个实例的基础上添加/删除任意属性),因此没有固定模式,也没有给定对象可能拥有或不拥有哪些属性的类级定义。


0
投票

因为,我被这个问题所吸引只是为了找到一个无用的答案,所以我找到了一个:

from collections import defaultdict, deque
from typing import List, Dict


class A:
    def __init__(self):
        self.value_a1 = 1
        self.value_a2 = 2


class B(A):
    def __init__(self):
        super().__init__()
        self.value_b1 = 3
        self.value_b2 = 4


class C(A):
    def __init__(self):
        super().__init__()
        self.value_c1 = 5
        self.value_c2 = 6


class D(B, C):
    def __init__(self):
        B.__init__(self)
        C.__init__(self)
        self.value_d1 = 7
        self.value_d2 = 8


class E(D):
    def __init__(self):
        super().__init__()
        self.value_e1 = 9
        self.value_e2 = 10


def build_inheritance_graph(classes) -> Dict[object, List[object]]:
    """

    :param classes:
    :return:
    """
    inheritance_graph = {}

    # Recursive function to populate the graph for a class and its ancestors
    def add_class_and_ancestors(cls):
        if cls not in inheritance_graph:
            inheritance_graph[cls] = list(cls.__bases__)
            for parent in cls.__bases__:
                add_class_and_ancestors(parent)

    for cls in classes:
        add_class_and_ancestors(cls)

    return inheritance_graph

def topological_sort(inheritance_graph) -> List[object]:
    """

    :param inheritance_graph:
    :return:
    """
    # Calculate in-degrees for each class
    in_degree = defaultdict(int)
    for cls, parents in inheritance_graph.items():
        in_degree[cls] += 0  # Ensure each class is initialized in in_degree
        for parent in parents:
            in_degree[parent] += 0
            in_degree[cls] += 1

    # Collect classes with no incoming edges (in-degree of 0)
    queue = deque([cls for cls, degree in in_degree.items() if degree == 0])
    sorted_classes = []

    while queue:
        cls = queue.popleft()
        sorted_classes.append(cls)

        for child, parents in inheritance_graph.items():
            if cls in parents:  # Check if cls is a parent of child
                in_degree[child] -= 1
                if in_degree[child] == 0:
                    queue.append(child)

    return sorted_classes


def get_declared_attributes(cls):
    """Return instance attributes defined directly in the given class's __init__."""
    # Create a temporary instance
    instance = cls()

    # Capture all instance attributes
    all_attrs = set(vars(instance).keys()) if hasattr(instance, '__dict__') else set()

    # Check parent classes to remove inherited attributes
    for base in cls.__bases__:
        parent_instance = base()
        parent_attrs = set(vars(parent_instance).keys()) if hasattr(parent_instance, '__dict__') else set()
        all_attrs -= parent_attrs

    return all_attrs

def get_mapping(classes):
    """

    :param classes: list of class types
    :return:
    """
    graph = build_inheritance_graph(classes)

    # Get classes sorted from least to most dependency
    sorted_classes_ = topological_sort(graph)

    props_by_class = list()

    # Display the sorted classes
    print("Classes sorted by dependency (from least to most):")
    for cls_ in sorted_classes_:
        props_list = get_declared_attributes(cls_)
        parents_list = [p.__name__ for p in graph[cls_]]
        # print(cls_.__name__, "->", parents_list, ": ", props_list)

        props_by_class.append({
            "class": cls_,
            "parents": parents_list,
            "properties": list(props_list)
        })

    return props_by_class

# Build the inheritance graph
mapping = get_mapping(classes=[B, C, D, E])

for item in mapping:
    print("class:", item['class'].__name__, "\n\tparents:", item['parents'], "\n\tproperties:", item['properties'])



© www.soinside.com 2019 - 2024. All rights reserved.