258

임의의 객체에서 사전을 작성하는 내장 함수가 있는지 알고 있습니까? 나는 이런 식으로하고 싶다 :

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

노트:메소드를 포함하지 않아야합니다. 필드 만.

11 답변


325

파이썬 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...


  • A 속성 중 하나에 맞춤 getter가 있으면 어떻게됩니까? (@property 데코레이터가있는 함수)? 그것은 ____dict____에 아직도 나타 납니까? 그 가치는 무엇일까요? - zakdances
  • __dict__객체가 슬롯을 사용하거나 (C 모듈에서 정의 된 경우) 작동하지 않습니다. - Antimony
  • 클래스 객체에 해당하는이 메서드가 있습니까? I.E. f = Foo ()를 사용하고 f .__ dict__을 수행하는 대신 Foo .__ dict__를 직접 수행 하시겠습니까? - chiffa
  • 죄송합니다. 늦게까지 방문하겠습니다.vars(a)이 작업을 수행? 나에게있어__dict__직접. - robert
  • 두 번째 예를 들면 더 좋을 것입니다.__getattr__ = dict.__getitem__정확하게 행동을 복제하려면, 당신은 또한__setattr__ = dict.__setitem____delattr__ = dict.__delitem__완전을 기원합니다. - Tadhg McDonald-Jensen

92

대신에x.__dict__실제로 사용하기에 훨씬 더 파이썬 스럽습니다.vars(x).


  • 동의했다. 다른 방법 (dict-> class)을 입력하여MyClass(**my_dict)클래스 속성을 반영하는 매개 변수를 사용하여 생성자를 정의했다고 가정합니다. 개인 속성에 액세스하거나 사전을 무시할 필요가 없습니다. - tvt173

53

그만큼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


  • 이 코드에는 메소드가 포함되어 있습니다. 메소드를 제외 할 수있는 방법이 있습니까? 개체 필드 만 있으면됩니다. 감사 - Julio César
  • ismethod기능을 포착 할 수 없습니다. 예:inspect.ismethod(str.upper).inspect.isfunction그래도 도움이되지는 않습니다. 이 방법에 즉시 접근하는 방법을 모릅니다. - Ehtesh Choudhury
  • 난 조심스럽게 되풀이하고 깊은 여기에 모든 오류를 무시하기 위해 몇 가지 개조했다, 감사합니다!gist.github.com/thorsummoner/bf0142fd24974a0ced778768a33a3069 - ThorSummoner

21

나는 두 가지 대답의 조합으로 해결했습니다.

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


  • 그것도 작동하지만 클래스에 대한 속성이 아니라 인스턴스에 설정된 속성 만 제공한다는 점에 유의하십시오 (예 : Foo 클래스) ... - dF.
  • 그래서, jcarrascal, 위의 코드를 props ()와 같은 함수로 래핑하는 것이 좋습니다. 그러면 props (f) 나 props (foo)를 호출 할 수 있습니다. 인라인을 쓰는 것보다는 거의 항상 함수를 작성하는 편이 낫다는 것을 주목하십시오. 암호. - quamrana

14

임의로 사전을 작성하는 방법목적, 사용하는 것으로 충분합니다.__dict__.

이것은 객체가 클래스에서 상속 한 속성을 누락시킵니다. 예를 들어,

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

hasattr (a, 'x')는 참이지만 'x'는 .__ dict__에 나타나지 않습니다.


11

나는 객체를 통해 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, 다음을 사용할 수 있습니다.updatedict 함수를 호출하고 인스턴스를 전달합니다.__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))


6

늦게 답변되었지만 Google 직원의 완성도와 혜택을 위해 제공되었습니다.

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

클래스에 정의 된 메소드는 표시되지 않지만 람다에 할당 된 필드 나 이중 밑줄로 시작하는 필드를 포함하는 필드는 계속 표시됩니다.


3

속성의 일부를 나열하려면 속성을 재정의하십시오.__dict__:

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

#Call __dict__
d = instance.__dict__()

이 기능을 사용하면instance큰 블록 데이터를 가져와 푸시하고 싶다.dRedis는 메시지 대기열과 같습니다.


3

가장 쉬운 방법은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개체 속성을 사전에 생성하고 사전 개체를 사용하여 필요한 항목을 가져올 수 있습니다.


  • 이 대답 후에도 개체에서 사전을 얻는 방법이 명확하지 않습니다. 속성이 아니라 전체 사전;) - maxkoryukov
  • @maxkoryukov 방금 대답을 업데이 트, 사용__dict__ - radtek

0

사용의 단점__dict__그것이 얕다는 것입니다; 하위 클래스를 사전으로 변환하지 않습니다.

Python3.5 이상을 사용하고 있다면jsons:

>>> import jsons
>>> jsons.dump(f)
{'bar': 'hello', 'baz': 'world'}


-1

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

연결된 질문


관련된 질문

최근 질문