424

任意のオブジェクトから辞書を作成する組み込み関数があるかどうか知っていますか? 私はこのようなことをしたいと思います:

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

注:メソッドを含めないでください。フィールドのみ。

4

16 に答える 16

535

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}

より良いアプローチ(コメントでロバートが提案は組み込み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...
于 2008-09-15T13:08:56.107 に答える
65

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
于 2008-09-14T18:07:55.507 に答える
31

私は両方の答えを組み合わせて解決しました:

dict((key, value) for key, value in f.__dict__.iteritems() 
    if not callable(value) and not key.startswith('__'))
于 2008-09-14T18:50:52.363 に答える
23

を介してオブジェクトを 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__関数です。

コメントで説明されているように、最初に行うことは、クラス アイテムを取得し、'__' で始まるものをすべて防止することです。

それを作成したら、 dict 関数をdict使用してインスタンスを渡すことができます。update__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))
于 2015-03-29T18:32:42.797 に答える
15

任意のオブジェクトから辞書を作成するには、を使用するだけで十分__dict__です。

これは、オブジェクトがそのクラスから継承する属性を見逃します。例えば、

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

hasattr(a、'x')はtrueですが、'x'はa.__dict__に表示されません

于 2008-09-15T14:56:01.030 に答える
1

上記のコメントの 1 つで述べたように、現在のところ、法線の代わりに をvars持つオブジェクトでは機能しないという点で普遍的ではありません。さらに、一部のオブジェクト (たとえば、orのような組み込み関数) には、 or がありませ__slots____dict__strint__dict__ __slots__

今のところ、より用途の広いソリューションは次のようになります。

def instance_attributes(obj: Any) -> Dict[str, Any]:
    """Get a name-to-value dictionary of instance attributes of an arbitrary object."""
    try:
        return vars(obj)
    except TypeError:
        pass

    # object doesn't have __dict__, try with __slots__
    try:
        slots = obj.__slots__
    except AttributeError:
        # doesn't have __dict__ nor __slots__, probably a builtin like str or int
        return {}
    # collect all slots attributes (some might not be present)
    attrs = {}
    for name in slots:
        try:
            attrs[name] = getattr(obj, name)
        except AttributeError:
            continue
    return attrs

例:

class Foo:
    class_var = "spam"


class Bar:
    class_var = "eggs"
    
    __slots__ = ["a", "b"]
>>> foo = Foo()
>>> foo.a = 1
>>> foo.b = 2
>>> instance_attributes(foo)
{'a': 1, 'b': 2}

>>> bar = Bar()
>>> bar.a = 3
>>> instance_attributes(bar)
{'a': 3}

>>> instance_attributes("baz") 
{}


暴言:

これがまだ組み込まれていないのは残念ですvars。Python の多くのビルトインは、問題の「解決策」になることを約束しますが、処理されない特殊なケースが常にいくつかあります...そして、いずれにしても手動でコードを書かなければならないことになります。

于 2020-12-27T18:23:45.067 に答える