[英]How to get all values of variables in class?
class NiceClass():
some_value = SomeObject(...)
some_other_value = SomeOtherObject(...)
@classmethod
def get_all_vars(cls):
...
I want get_all_vars()
to return [SomeObject(...), SomeOtherObject(...)]
, or more specifically, the values of the variables in cls
.我希望get_all_vars()
返回[SomeObject(...), SomeOtherObject(...)]
,或者更具体地说,返回cls
中变量的值。
Solutions tried that didn't work out for me:尝试过的解决方案对我没有用:
return [cls.some_value, cls.some_other_value, ...]
(requires listing the variable manually) return [cls.some_value, cls.some_other_value, ...]
(需要手动列出变量)Enum
then using list(cls)
(requires using some_value.value
to access the value elsewhere in the program, also type hinting would be a mess)子类化Enum
然后使用list(cls)
some_value.value
Enum
) namedtuples(不涉及那个主题,听说它比Enum
复杂得多)[value for key, value in vars(cls).items() if not callable(value) and not key.startswith("__")]
(too hacky due to using vars(cls)
, also for some reason it also includes get_all_vars
due to it being a classmethod
) [value for key, value in vars(cls).items() if not callable(value) and not key.startswith("__")]
(由于使用vars(cls)
太老套了,也出于某种原因它还包括get_all_vars
因为它是一个classmethod
)There are two ways.有两种方法。 This is a straight answer to your question:这是对您问题的直接回答:
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
This is what I suggest:这就是我的建议:
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)]
results:结果:
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]
You can create a list of values and define individual attributes at the same time with minimal boilerplate.您可以使用最少的样板同时创建一个值列表并定义各个属性。
class NiceClass():
(some_value,
some_other_value,
) = _all_values = [
SomeObject(...),
SomeOtherObject(...)
]
@classmethod
def get_all_vars(cls):
return cls._all_values
The most obvious drawback to this is that it's easy to get the order of names and values out of sync.这样做最明显的缺点是很容易使名称和值的顺序不同步。
Ideally, you might like to do something like理想情况下,您可能想做类似的事情
class NiceClass:
_attributes = {
'some_value': SomeObject(...),
'some_other_value': SomeOtherObject(...)
}
@classmethod
def get_all_vars(cls):
return cls._attributes.values()
and have some way to "inject" the contents of _attributes
into the class namespace directly.并有办法将_attributes
的内容直接“注入”到 class 命名空间中。 The simplest way to do this is with a mix-in class that defines __init_subclass__
:最简单的方法是使用定义 __init_subclass__ 的混合__init_subclass__
:
class AddAttributes:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
cls.__dict__.update(cls._attributes)
class NiceClass(AddAttributes):
# As above
...
This might sound like a https://xyproblem.info/ but my solution might work in the other case as well.这可能听起来像https://xyproblem.info/但我的解决方案也可能适用于其他情况。 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 )您可以使用__dict__
或vars
获取 object 的字段(考虑到更多 pythonic: Python dictionary from an object's fields )
You could do something like:你可以这样做:
class ClassTest:
def __init__(self):
self.one = 1
self.two = 2
list(vars(ClassTest()).values())
But you will see that it has some limitations.但是您会发现它有一些局限性。 It doesn't recognize the not in self.variable_name
defined variables like you have used above.它无法识别您在上面使用的 not in self.variable_name
定义的变量。 It might help you n.netheless, because you can simply define them in init.尽管如此,它可能对您有所帮助,因为您可以简单地在 init 中定义它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.