Python对象字段中的字典

你知道是否有一个内置的函数来从任意对象build立一个字典? 我想要做这样的事情:

>>> class Foo: ... bar = 'hello' ... baz = 'world' ... >>> f = Foo() >>> props(f) { 'bar' : 'hello', 'baz' : 'world' } 

注意:它不应该包括方法。 只有领域。

请注意,Python 2.7中的最佳做法是使用新式类(Python 3不需要),即

 class Foo(object): ... 

另外,“对象”和“类”之间也有区别。 要从任意对象构build字典,使用__dict__就足够了。 通常,你将在类级别声明你的方法,在实例级声明你的属性,所以__dict__应该没问题。 例如:

 >>> class A(object): ... def __init__(self): ... self.b = 1 ... self.c = 2 ... def do_nothing(self): ... pass ... >>> a = A() >>> a.__dict__ {'c': 2, 'b': 1} 

更好的方法(由罗伯特在评论中提出)是内buildvars函数:

 >>> vars(a) {'c': 2, 'b': 1} 

另外,取决于你想做什么,它可能是很好的从dictinheritance。 那么你的类已经是一个字典,如果你想要,你可以重写getattr和/或setattr来调用,并设置字典。 例如:

 class Foo(dict): def __init__(self): pass def __getattr__(self, attr): return self[attr] # etc... 

dir builtin会给你所有对象的属性,包括特殊的方法,如__str____str__和其他一些你可能不想要的东西。 但是你可以做一些事情:

 >>> class Foo(object): ... bar = 'hello' ... baz = 'world' ... >>> f = Foo() >>> [name for name in dir(f) if not name.startswith('__')] [ 'bar', 'baz' ] >>> dict((name, getattr(f, name)) for name in dir(f) if not name.startswith('__')) { 'bar': 'hello', 'baz': 'world' } 

所以可以扩展这个只返回数据属性而不是方法,通过定义你的props函数是这样的:

 import inspect def props(obj): pr = {} for name in dir(obj): value = getattr(obj, name) if not name.startswith('__') and not inspect.ismethod(value): pr[name] = value return pr 

而不是x.__dict__ ,实际上使用vars(x)更加pythonic。

我已经解决了两个答案的组合:

 dict((key, value) for key, value in f.__dict__.iteritems() if not callable(value) and not key.startswith('__')) 

要从任意对象构build字典,使用__dict__就足够了。

这忽略了对象从它的类inheritance的属性。 例如,

 class c(object): x = 3 a = c() 

hasattr(a,'x')为真,但'x'不出现在.__ dict__中

我想我会花一些时间来告诉你如何通过dict(obj)将对象转换为字典。

 class A(object): d = '4' e = '5' f = '6' def __init__(self): self.a = '1' self.b = '2' self.c = '3' def __iter__(self): # first start by grabbing the Class items iters = dict((x,y) for x,y in A.__dict__.items() if x[:2] != '__') # then update the class items with the instance items iters.update(self.__dict__) # now 'yield' through the items for x,y in iters.items(): yield x,y a = A() print(dict(a)) # prints "{'a': '1', 'c': '3', 'b': '2', 'e': '5', 'd': '4', 'f': '6'}" 

这段代码的关键部分是__iter__函数。

正如评论所解释的那样,我们要做的第一件事就是抓住Class项目,并防止以“__”开头的任何内容。

一旦你创build了这个dict ,那么你可以使用update字典function,并传递实例__dict__

这些会给你一个完整的类+实例字典的成员。 现在剩下的就是遍历它们并产生回报。

另外,如果你打算使用这个,你可以创build一个@iterable类装饰器。

 def iterable(cls): def iterfn(self): iters = dict((x,y) for x,y in cls.__dict__.items() if x[:2] != '__') iters.update(self.__dict__) for x,y in iters.items(): yield x,y cls.__iter__ = iterfn return cls @iterable class B(object): d = 'd' e = 'e' f = 'f' def __init__(self): self.a = 'a' self.b = 'b' self.c = 'c' b = B() print(dict(b)) 

迟到的答案,但提供了完整性和谷歌的好处:

 def props(x): return dict((key, getattr(x, key)) for key in dir(x) if key not in dir(x.__class__)) 

这不会显示在类中定义的方法,但它仍然会显示字段,包括分配给lambdaexpression式的字段或以双下划线开头的字段。

如果您想列出部分属性,请覆盖__dict__

 def __dict__(self): d = { 'attr_1' : self.attr_1, ... } return d # Call __dict__ d = instance.__dict__() 

如果你的instance得到了一些大的块数据,并且你想把d推到Redis,比如消息队列,这会有很大帮助。

我认为最简单的方法是为这个类创build一个getitem属性。 如果您需要写入对象,则可以创build自定义setattr 。 这里是一个getitem的例子:

 class A(object): def __init__(self): self.b = 1 self.c = 2 def __getitem__(self, item): return self.__dict__[item] # Usage: a = A() a.__getitem__('b') # Outputs 1 a.__dict__ # Outputs {'c': 2, 'b': 1} vars(a) # Outputs {'c': 2, 'b': 1} 

dict将对象属性生成为一个字典,字典对象可以用来获取你需要的项目。