从对象字段创建Python字典

508 投票
21 回答
767974 浏览
提问于 2025-04-11 00:00

你知道有没有内置的函数可以从一个任意对象创建字典吗?我想做类似这样的事情:

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

注意:它只应该包含字段,不包括方法。

21 个回答

73

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
248

与其使用 x.__dict__,不如用 vars(x) 这种写法更符合 Python 的风格。

613

请注意,在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...

撰写回答