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

Python 如何在不知道类的名称的情况下获取类的属性,python,Python,我有以下课程: class TestClass(object): def __init__(self, **kwargs): for key, value in kwargs.items(): #items return list of dict setattr(self, key, value) 示例用途: obj = MessageItem(**{"testkey1":"tval1", "tkey2":"tval2", "tkey3":"tval3"}) 如何在不

我有以下课程:

class TestClass(object):
def __init__(self, **kwargs):
    for key, value in kwargs.items(): #items return list of dict
        setattr(self, key, value)
示例用途:

obj = MessageItem(**{"testkey1":"tval1", "tkey2":"tval2", "tkey3":"tval3"})
如何在不知道属性名称的情况下迭代此结构?Python为我们提供了内置方法
\uuuu getattribute\uuu
,但我仍然需要知道请求的属性的名称:

print(obj.__getattribute__("testkey1"))

\uuuu dict\uuu
属性保存您想要的内容。 班级有:

>>> 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})
您应该通过
vars
内置函数访问此属性。 调用
vars(foo)
将返回
foo.\uuuu dict\uuuu
。 请参阅此相关帖子:

:

变量([对象])

返回模块、类、实例或任何其他具有
\uuuuuuuu dict\uuu
属性的对象的
\uuuuu dict\uuuuu
属性

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)
模块和实例等对象具有可更新的
\uu dict\uu
属性;但是,其他对象可能对其
\uuuu dict\uuuu
属性(例如,类使用
types.MappingProxyType
来防止直接更新字典)

没有参数,
vars()
的行为类似于
locals()
。注意,局部变量字典仅对读取有用,因为它更新了局部变量 字典被忽略了


此外,我还试着写了一个你可能感兴趣的装饰师。 这是一个类装饰器,它向它装饰的类添加一个
initKwargs
。 此外,它还包装了该类的
\uuuu init\uuuu
方法,以便将它接收到的
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)
演示:

>>> 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}]
我发现这种方法比使用
vars
要干净得多,因为您自己定义了它,所以知道要访问什么。
它可以让你更好地控制班级的行为。

你为什么要故意将自己置于这种情况下,而不是将其存储为
指令?@JonClements个人而言,我不知道,我的领导是这样计划的,我必须实现:停下来,随意告诉他们这不是一个好的设计,有点危险。。。人们将能够重击你已经使用过的名称,并破坏一些东西,以后调试它将变得非常糟糕。(或者相反,你可能会重击对他们传递的变量的赋值…)并且只需注意(在大多数用例中这是一个坏主意):你不会真的想使用
obj.\uu getattribute\uuuu(“testkey1”)
-您将使用
getattr(obj,'testkey1')
-不仅在眼睛和键盘上更容易操作,而且还允许在未找到属性时提供返回的默认值。如果您要建议,则建议使用
vars(f)
-这里几乎不需要直接访问
\uuuu dict\uuuu
,而且可能并不总是如预期的那样。@JonClements考虑到文档中关于
变量的内容,它与
\uu dict\uuu
有什么不同?我想我记得读过那篇文章,说得不太好,但我记不起为什么了……我记不清了。。。但是,
vars(…)
将做正确的事情,而直接访问
\uu dict\uuu
在某些情况下可能会失败。虽然我现在有点怀疑自己。。。但有一件事让我想起了:)此外——至少——在代码中没有dunder方法访问权,在不必要的地方总是好的。@JonClements我发现。因此,基本的论点是,由于Python为它提供了一个包装器,所以应该通过该包装器而不是直接访问它。这对我来说很有意义,很好的发现。谢谢现在-唯一的问题是,你不能真正告诉什么参数提供了,除非你拿走了那些已经在那里或知道你已经设置了。。。但是,如果老年退休金计划采取这种做法,那么,好吧,就在他们头上吧。