개발하자

파이썬에서 dir()와 __dict_의 가장 큰 차이점은 무엇입니까

Cuire 2023. 6. 21. 16:00
반응형

파이썬에서 dir()와 __dict_의 가장 큰 차이점은 무엇입니까

class C(object):
    def f(self):
        print self.__dict__
        print dir(self)
c = C()
c.f()

출력:

{}

['__class__', '__delattr__','f',....]

왜 자기 안에 'f'가 없는지.__filen__




올려다보는 것 이상의 일을 한다

우선, 객체의 속성을 조회하는 것과 같은 속성을 사용하는 방법을 아는 API 방법이다.

그러나 모든 개체에 속성이 있는 것은 아닙니다. 예를 들어 사용자 지정 클래스에 를 추가하는 경우 해당 클래스의 인스턴스에는 속성이 없지만 해당 인스턴스에서 사용 가능한 속성을 나열할 수 있습니다:

>>> class Foo(object):
...     __slots__ = ('bar',)
...     bar = 'spam'
... 
>>> Foo().__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__dict__'
>>> dir(Foo())
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'bar']

이는 많은 기본 제공 유형에 적용됩니다. 에서는 속성이 없지만 다음을 사용하여 모든 속성을 나열할 수 있습니다:

>>> [].__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__dict__'
>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

인스턴스는 어떻게 됩니까

Python 인스턴스는 고유하지만 클래스도 고유합니다:

>>> class Foo(object):
...     bar = 'spam'
... 
>>> Foo().__dict__
{}
>>> Foo.__dict__.items()
[('__dict__', <attribute '__dict__' of 'Foo' objects>), ('__weakref__', <attribute '__weakref__' of 'Foo' objects>), ('__module__', '__main__'), ('bar', 'spam'), ('__doc__', None)]

메소드는 인스턴스, 클래스 및 클래스의 모든 상위 항목에서 사용 가능한 속성의 전체 목록을 만드는 데 사용됩니다.

클래스에 속성을 설정하면 다음과 같은 인스턴스도 표시됩니다:

>>> f = Foo()
>>> f.ham
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'ham'
>>> Foo.ham = 'eggs'
>>> f.ham
'eggs'

속성이 클래스에 추가되기 때문입니다:

>>> Foo.__dict__['ham']
'eggs'
>>> f.__dict__
{}

인스턴스가 비어 있는 상태로 유지되는 방법을 참조하십시오. Python 객체에 대한 속성 조회는 인스턴스에서 유형, 부모 클래스까지 객체의 계층 구조를 따라 속성을 검색합니다.

클래스가 변경되지 않은 상태로 유지되는 동안 인스턴스에서 직접 특성을 설정한 경우에만 인스턴스의 에 반영된 특성을 볼 수 있습니다:

>>> f.stack = 'overflow'
>>> f.__dict__
{'stack': 'overflow'}
>>> 'stack' in Foo.__dict__
False

TLDR; or the summary

dir() doesn't just look up an object's __dict__ (which sometimes doesn't even exist), it will use the object's heritage (its class or type, and any superclasses, or parents, of that class or type) to give you a complete picture of all available attributes.

An instance __dict__ is just the 'local' set of attributes on that instance, and does not contain every attribute available on the instance. Instead, you need to look at the class and the class's inheritance tree too.




The function f belongs to the dictionary of class C. c.__dict__ yields attributes specific to the instance c.

>>> class C(object):
    def f(self):
        print self.__dict__


>>> c = C()
>>> c.__dict__
{}
>>> c.a = 1
>>> c.__dict__
{'a': 1}

C.__dict__ would yield attributes of class C, including function f.

>>> C.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'C' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None, 'f': <function f at 0x0313C1F0>})

While an object can refer to an attribute of its class (and indeed all the ancestor classes), the class attribute so referred does not become part of the associated dict itself. Thus while it is legitimate access to function f defined in class C as c.f(), it does not appear as an attribute of c in c.__dict__.

>>> c.a = 1
>>> c.__dict__
{'a': 1}



Class dir() and __dict__ only show defined functions (methods). Instance dir() shows data+methods while its __dict__ only shows data attributes, not methods.

class C2:
...     def __init__(self, id): 
...         self.id = id
...     def set(self, len):
...         self.len = len        
...         
c2 = C2("stick")
dir(C2)
['__class__',.., '__init__', 'set']
dir(c2)
['__class__',.., '__init__', 'id', 'set']
C2.__dict__
mappingproxy({'__init__': <function C2.__init__ at 0x000001899C61E9D0>, 'set': <function C2.set at 0x000001899C61ED30>,...})
c2.__dict__
{'id': 'stick'}

반응형