Python 使用vars()仅检索自己的属性
在python中,Python 使用vars()仅检索自己的属性,python,python-3.x,class,attributes,Python,Python 3.x,Class,Attributes,在python中,vars()检索对象的所有属性。对于从其他类派生的类的实例,是否有一种方便的方法过滤掉“继承的”属性?我这样做的目的是仅在自己的属性上定义\uuuu eq\uu比较 根据我的理解,这些属性不是继承的,而是直接存在于对super()的调用的实例中。\uu init\uu(),因此不会有内置的分离机制 class Base: def __init__(self): self.a = 0 class Derived(Base): def __ini
vars()
检索对象的所有属性。对于从其他类派生的类的实例,是否有一种方便的方法过滤掉“继承的”属性?我这样做的目的是仅在自己的属性上定义\uuuu eq\uu
比较
根据我的理解,这些属性不是继承的,而是直接存在于对super()的调用的实例中。\uu init\uu()
,因此不会有内置的分离机制
class Base:
def __init__(self):
self.a = 0
class Derived(Base):
def __init__(self):
super().__init__()
self.b = 1
derived = Derived()
# results in {'a': 0, 'b': 1}
# how can I make this return {'b': 1}?
print(vars(derived))
我当前的解决方案可行,但需要为每个类定义它:
class Derived(Base):
def __init__(self):
super().__init__()
pre_init_attrs = set(vars(self).keys())
# own init
self.b = 1
# process own init
post_init_attrs = set(vars(self).keys())
self._own_attrs = post_init_attrs.difference(pre_init_attrs)
def vars(self):
return {key: self.__dict__[key] for key in self._own_attrs}
有没有一种方法可以通过修饰符或元类来实现这一点?您所要求的与Python中类的工作方式不太一样
vars
已经从基类中过滤出继承的属性
但是self.a
不是继承的。它被显式地添加到您的self
实例中,因为您的\uuu init\uu
显式地调用super()。如果您的\uuu init\uuu
调用了self.addx()
,并且派生的.addx
方法执行了self.x=0
,那么该调用实际上没有什么特别之处,它的工作方式与您在这里所做的完全相同
你可以写一个装饰师来做你想做的事,但也许退一步更好
为什么不存储希望每个类作为类的一部分提供的字段列表
或者,既然您似乎试图模拟更像Java风格的类,其中每个类的属性集都是固定的,那么为什么不直接使用@dataclass
(或者,如果您需要3.7之前的兼容性或额外功能,则使用第三方@attr.s
)呢?这会自动记录哪些字段属于哪个类,以及与之相关的许多其他事情
>>> from dataclasses import dataclass, fields
>>>
>>>> @dataclass
... class Base:
... a: int = 0
...
>>> @dataclass
... class Derived(Base):
... b: int = 1
...
>>> derived = Derived()
>>> derived
Derived(a=0, b=1)
>>> def ownfields(obj):
... fs = fields(obj)
... for base in type(obj).__bases__:
... basefs = set(fields(base))
... fs = [f for f in fs if f not in basefs]
... return fs
...
>>> ownfields(derived)
[Field(name='b',type=<class 'int'>,default=1,default_factory=<dataclasses._MISSING_TYPE object at 0x10571ca58>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD)]
>>> def ownvars(obj):
... return {field.name: getattr(obj, field.name) for field in ownfields(obj)}
...
>>> ownvars(derived)
{'b': 1}
例如,如果您从多个类继承,而这些类本身不是数据类,但都是以菱形模式从数据类继承,那么这仍然不起作用。我不确定在这种情况下,预期的行为是什么。可能只需遵循类型(obj).mro()[1://code>?这不会比其他任何事情更令人惊讶,而且它似乎是与查找最一致的并行…感谢您给我指出ATTR;我听说过数据类,但代码库是3.7之前的版本。注意,我已经知道“继承的”属性不是继承的,而是直接在派生实例上定义的。我提到“继承的”属性(带引号)作为引用这些属性的一种方式,而不是“从派生实例中对基初始值设定项的调用中定义的属性”@LemonPi Right;关键是,跟踪属性可能比动态计算属性更好,至少如果您可以通过使用类似于@dataclass
或@attr.s
或\uuu slots\uuu
的方法进一步利用相同的信息,我想在这种情况下您可以这样做。
>>> def ownfields(obj):
... fs = fields(obj)
... for base in type(obj).__bases__:
... try:
... basefs = set(fields(base))
... except TypeError:
... pass
... else:
... fs = [f for f in fs if f not in basefs]
... return fs