来自对象字段的Python字典

时间:2020-03-05 18:53:02  来源:igfitidea点击:

我们是否知道是否有内置函数可以从任意对象构建字典?我想做这样的事情:

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

注意:它不应包含方法。仅字段。

解决方案

回答

内置的dir将为我们提供对象的所有属性,包括特殊方法,如__str__,__dict__以及我们可能不希望使用的其他方法。但是我们可以执行以下操作:

>>> 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

回答

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

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

回答

请注意,Python 2.7中的最佳实践是使用新型类(Python 3不需要),即

class Foo(object):
   ...

同样,"对象"和"类"之间也存在差异。要从任意对象构建字典,使用__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}

更好的方法(由robert建议在注释中使用)是内置的vars函数:

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

另外,根据我们想做什么,最好继承自dict。然后班级已经是字典,并且如果我们愿意,可以覆盖getattr和/或者setattr来调用并设置字典。例如:

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

    # etc...

回答

To build a dictionary from an arbitrary object, it's sufficient to use __dict__.

这会错过对象从其类继承的属性。例如,

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

hasattr(a,'x')是true,但是'x'不会出现在a中。dict