如何在不知道名称的情况下获取类的属性

Rob*_*lak 5 python

我有以下课程:

class TestClass(object):
def __init__(self, **kwargs):
    for key, value in kwargs.items(): #items return list of dict
        setattr(self, key, value)
Run Code Online (Sandbox Code Playgroud)

示例使用:

obj = MessageItem(**{"testkey1":"tval1", "tkey2":"tval2", "tkey3":"tval3"})
Run Code Online (Sandbox Code Playgroud)

如何在不知道属性名称的情况下迭代此结构?Python 为我们提供了内置方法__getattribute__,但我仍然需要知道请求的属性的名称:

print(obj.__getattribute__("testkey1"))
Run Code Online (Sandbox Code Playgroud)

Rig*_*leg 4

__dict__属性包含您想要的内容。该类有:

>>> class Foo:
...     def __init__(self, x):
...             self.x = x
...
>>> Foo.__dict__
mappingproxy({'__module__': '__main__', '__init__': <function Foo.__init__ at
0x000001CC1821EEA0>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__':
<attribute '__weakref__' of 'Foo' objects>, '__doc__': None})
Run Code Online (Sandbox Code Playgroud)

任何实例也有它:

>>> f = Foo(2)
>>> f.__dict__
{'x': 2}
Run Code Online (Sandbox Code Playgroud)

您应该通过内置函数访问此属性vars。调用vars(foo)就会返回foo.__dict__。请参阅此相关帖子:使用__dict__vars()

文档vars

变量([对象])

返回__dict__模块、类、实例或任何其他具有__dict__属性的对象的属性。

模块和实例等对象具有可更新的__dict__属性;但是,其他对象可能对其 __dict__属性有写限制(例如,类使用 atypes.MappingProxyType来防止直接更新字典)。

没有参数,vars()行为就像locals(). 请注意,本地字典仅对读取有用,因为本地字典的更新会被忽略。


此外,我尝试并编写了一个您可能感兴趣的装饰器。这是一个类装饰器,它将 a 添加initKwargs到它所装饰的类中。此外,它还包装了__init__该类的方法,以便将其kwargs接收到的字典附加到该类的initKwargs属性中。

def class_wrapper(cls):
    cls.initKwargs = []
    f = cls.__init__

    def wrapped_init(instance, **kwargs):
        cls.initKwargs.append(kwargs)
        return f(instance, **kwargs)            
    cls.__init__ = wrapped_init

    return cls

@class_wrapper
class Foo:
    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)
Run Code Online (Sandbox Code Playgroud)

示范:

>>> f1 = Foo()
>>> f2 = Foo(a=1, b=2)
>>> f3 = Foo(a=1, b=2, c=3, d=4)
>>> Foo.initKwargs
[{}, {'a': 1, 'b': 2}, {'a': 1, 'b': 2, 'c': 3, 'd': 4}]
Run Code Online (Sandbox Code Playgroud)

我发现这种方法比使用 更干净vars,因为您知道自己正在访问什么,因为您自己定义了它。它使您可以更好地控制班级的行为。

  • 如果您要建议,那么建议使用 `vars(f)` - 几乎不需要在这里直接访问 `__dict__` 并且它可能并不总是如预期的那样。 (2认同)