首页 文章

来自对象字段的Python字典

提问于
浏览
256

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

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

NOTE: 它不应该包括方法 . 只有字段 .

10 回答

  • 3

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

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

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

    这会遗漏对象从其类继承的属性 . 例如,

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

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

  • 6

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

    class Foo(object):
       ...
    

    还有,'s a difference between an ' object ' and a ' class' . 要从任意对象构建字典,使用 __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...
    
  • 324

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

  • 92

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

    我想我会花一些时间向你展示如何通过 dict(obj) 将对象翻译成dict .

    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__ 函数 .

    正如评论所解释的那样,我们要做的第一件事就是 grab Class项并防止任何以'__'开头的内容 .

    一旦你创建了 dict ,那么你可以使用 update dict函数并传入实例 __dict__ .

    这些将为您提供完整的成员类实例字典 . 现在剩下的就是迭代它们并产生回报 .

    此外,如果您打算大量使用它,您可以创建一个 @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))
    
  • 11

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

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

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

  • 3

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

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

    如果您的 instance 获取一些大块数据并且您想将 d 推送到Redis之类的消息队列,这会有很大帮助 .

  • -1

    我认为最简单的方法是为类创建 getitem 属性 . 如果需要写入对象,可以创建自定义 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 将对象属性生成到字典中,字典对象可用于获取所需的项目 .

  • 14

    PYTHON 3:

    class DateTimeDecoder(json.JSONDecoder):
    
       def __init__(self, *args, **kargs):
            JSONDecoder.__init__(self, object_hook=self.dict_to_object,
                             *args, **kargs)
    
       def dict_to_object(self, d):
           if '__type__' not in d:
              return d
    
           type = d.pop('__type__')
           try:
              dateobj = datetime(**d)
              return dateobj
           except:
              d['__type__'] = type
              return d
    
    def json_default_format(value):
        try:
            if isinstance(value, datetime):
                return {
                    '__type__': 'datetime',
                    'year': value.year,
                    'month': value.month,
                    'day': value.day,
                    'hour': value.hour,
                    'minute': value.minute,
                    'second': value.second,
                    'microsecond': value.microsecond,
                }
            if isinstance(value, decimal.Decimal):
                return float(value)
            if isinstance(value, Enum):
                return value.name
            else:
                return vars(value)
        except Exception as e:
            raise ValueError
    

    现在您可以在自己的类中使用上面的代码:

    class Foo():
      def toJSON(self):
            return json.loads(
                json.dumps(self, sort_keys=True, indent=4, separators=(',', ': '), default=json_default_format), cls=DateTimeDecoder)
    
    
    Foo().toJSON()
    

相关问题