如何获取class中变量的所有值?

How to get all values of variables in class?

class NiceClass():
    some_value = SomeObject(...)
    some_other_value = SomeOtherObject(...)

    @classmethod
    def get_all_vars(cls):
        ...

我想要get_all_vars()到return[SomeObject(...), SomeOtherObject(...)],或者更具体地说,cls.中变量的值

尝试过但对我不起作用的解决方案:

这听起来可能像 https://xyproblem.info/ but my solution might work in the other case as well. You can get the fields of an object by using __dict__ or vars (which is considered more pythonic given: Python dictionary from an object's fields)

你可以这样做:

class ClassTest:
   def __init__(self):
      self.one = 1
      self.two = 2
list(vars(ClassTest()).values())

但是您会发现它有一些局限性。它无法识别 not in self.variable_name 定义的变量,就像您在上面使用的那样。尽管如此,它可能对您有所帮助,因为您可以简单地在 init 中定义它们。

有两种方法。这是对您问题的直接回答:

class Foo:
    pass


class Bar:
    x: int = 1
    y: str = 'hello'
    z: Foo = Foo()

    @classmethod
    def get_all(cls):
        xs = []
        for name, value in vars(cls).items():
            if not (name.startswith('__') or isinstance(value, classmethod)):
                xs.append(value)
        return xs

这是我的建议:

from dataclasses import dataclass, fields


class Foo:
    pass


@dataclass
class Bar:
    x: int = 1
    y: str = 'hello'
    z: Foo = Foo()

    @classmethod
    def get_defaults(cls):
        return [f.default for f in fields(cls)]

    @classmethod
    def get_all(cls):
        return [getattr(cls, f.name) for f in fields(cls)]

结果:

Bar.get_defaults() == Bar.get_all()
# True -> [1, 'hello', __main__.Foo]

Bar.x = 10
Bar.get_defaults() == Bar.get_all()
# False -> [1, 'hello', __main__.Foo] != [10, 'hello', __main__.Foo]

您可以创建一个值列表 同时使用最少的样板文件定义各个属性。

class NiceClass():
    (some_value,
     some_other_value,
    ) = _all_values = [
        SomeObject(...),
        SomeOtherObject(...)
    ]
    

    @classmethod
    def get_all_vars(cls):
        return cls._all_values

这样做最明显的缺点是很容易使名称和值的顺序不同步。

理想情况下,您可能喜欢做类似

的事情
class NiceClass:

    _attributes = {
        'some_value': SomeObject(...),
        'some_other_value': SomeOtherObject(...)
    }

    @classmethod
    def get_all_vars(cls):
        return cls._attributes.values()

并有一些方法可以将 _attributes 的内容直接“注入”到 class 命名空间中。最简单的方法是使用 mix-in class 定义 __init_subclass__:

class AddAttributes:
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.__dict__.update(cls._attributes)


class NiceClass(AddAttributes):
    # As above
    ...