IT

__dict__ 속성 설명

itgroup 2023. 7. 22. 09:56
반응형

__dict__ 속성 설명

나는 정말 혼란스럽습니다.__dict__기다하여. 검색을 요.제가 검색을 많이 해봤지만 출력은 잘 모르겠습니다.

객체, 클래스 또는 함수에 사용되는 경우 이 속성을 0부터 사용하는 방법을 설명할 수 있는 사람이 있습니까?

기본적으로 문제의 개체를 설명하는 모든 속성을 포함합니다.속성을 변경하거나 읽는 데 사용할 수 있습니다.다음에 대한 설명서에서 인용한 내용

개체의(쓰기 가능한) 특성을 저장하는 데 사용되는 사전 또는 기타 매핑 개체입니다.

Python에서는 모든 것이 객체라는 것을 기억하세요.제가 모든 것을 말할 때, 저는 기능, 클래스, 객체 등 모든 것을 의미합니다. (Ya 제대로 읽으셨군요, 클래스.클래스도 개체입니다.예:

def func():
    pass

func.temp = 1

print(func.__dict__)

class TempClass:
    a = 1
    def temp_function(self):
        pass

print(TempClass.__dict__)

will 출력

{'temp': 1}
{'__module__': '__main__', 
 'a': 1, 
 'temp_function': <function TempClass.temp_function at 0x10a3a2950>, 
 '__dict__': <attribute '__dict__' of 'TempClass' objects>, 
 '__weakref__': <attribute '__weakref__' of 'TempClass' objects>, 
 '__doc__': None}

Python 문서의 정의는 다음과 같습니다.

개체의(쓰기 가능한) 특성을 저장하는 데 사용되는 사전 또는 기타 매핑 개체입니다.

그러나 이 정의는 약간 모호하여 많은 잘못된 사용으로 이어집니다.__dict__.

실제로, 당신이 이 정의를 읽을 때, 무엇이 "쓰기 가능한" 속성이고 무엇이 아닌지 알 수 있습니까?


얼마나 혼란스럽고 부정확할 수 있는지 보여주는 몇 가지 예를 들어 보겠습니다.

class A:

    foo = 1

    def __init__(self):
        self.bar = 2

    @property
    def baz(self):
        return self._baz

    @bar.setter
    def baz(self, value):
        self._baz = value

>>> a = A()
>>> a.foo
1
>>> a.bar
2

의 클래스가 때A그리고 알고 있는__dict__의 정의, 당신은 무엇이 가치가 있는지 추측할 수 있습니까?a.__dict__?

  • 아이즈foo의 쓰기 a?
  • 아이즈bar의 쓰기 a?
  • 아이즈baz의 쓰기 a?
  • 아이즈_baz의 쓰기 a?

정답은 다음과 같습니다.

>>> a.__dict__
{'bar': 2}

놀게도랍.foo나타나지 않습니다.실제로, 비록 접근이 가능하지만.a.foo입니다.A 런경우아닌가그a.

이제우그것명시로속될어까요정떻의 속성으로 될까요?a?

>>> a.foo = 1
>>> a.__dict__
{'bar': 2, 'foo': 1}

것은 아무것도 , 우의관점볼때, 아것도변없다습.a.foo 여히전 와같다니습과 .1하지만 지금은 그것이 나타납니다.__dict__삭제하여 계속 재생할 수 있습니다.a.foo예를 들어:

>>> del a.foo
>>> a.__dict__
{'bar': 2}
>>> a.foo
1

여기서 무슨 일이 일어났냐면 우리가 인스턴스 속성을 삭제하고 전화를 걸었습니다.a.foo 다시뒤물다서러로로 떨어집니다.A.foo.

어디보나에 대해 하겠습니다baz 금지에서는 수 볼 수 . 우리는 우리가 그것을 찾을 수 없다고 가정할 수 있습니다.a.__dict__아직 가치를 부여하지 않았기 때문입니다.

>>> a.baz = 3

자, 이제 우리는 정의했습니다.a.baz그래서?baz쓰기 가능한 속성? 때어는?_baz?

>>> a.__dict__
{'bar': 2, '_baz': 3}

__dict__의관에서보면점,_baz 가능한이지만 쓰기 가특 지이만baz그렇지 않아요. 다시 말하지만, 그 설명은.baz입니다.A 렇지않이 .a.

>>> A.__dict__['baz']
<property at 0x7fb1e30c9590>

a.baz는 추화계호뿐입다니일출층상다를 호출하는 입니다.A.baz.fget(a)

우리의 소중한 친구와 더욱 교활해지고 "쓰기 가능"의 정의에 도전해 봅시다.

class B:

    def __init__(self):
        self.foobar = 'baz'

    def __setattr__(self, name, value):
        if name == 'foobar' and 'foobar' in self.__dict__:
            # Allow the first definition of foobar
            # but prevent any subsequent redefinition
            raise TypeError("'foobar' is a read-only attribute")
        super().__setattr__(name, value)

>>> b = B()
>>> b.foobar
'baz'
>>> b.foobar = 'bazbar'
TypeError: 'foobar' is a read-only attribute
>>> # From our developer's perspective, 'foobar' is not a writable attribute
>>> # But __dict__ doesn't share this point of view
>>> b.__dict__
{'foobar': 'baz'}

그렇다면 무엇입니까?__dict__정확히?

위의 예들에서 발견된 행동 덕분에, 우리는 이제 무엇을 더 잘 이해할 수 있습니다.__dict__실제로 그렇습니다.그러나 우리는 개발자의 관점에서 컴퓨터의 관점으로 전환해야 합니다.

__dict__이 특정 개체에 대한 프로그램의 메모리에 저장된 데이터를 포함합니다.

바로 그겁니다.__dict__실제 메모리에 저장된 내용을 객체의 주소에 표시합니다.

데이터 모델에 대한 Python 문서는 또한 객체의 네임스페이스로 정의합니다.

클래스 인스턴스에는 속성 참조가 검색되는 첫 번째 위치인 사전으로 구현된 네임스페이스가 있습니다.속성을 찾을 수 없고 인스턴스의 클래스에 해당 이름의 속성이 있으면 클래스 속성으로 검색이 계속됩니다.

저는 하만지생,각합다니저는을 을 믿습니다.__dict__개체의 메모리 테이블에서 이 네임스페이스에 포함된 항목과 포함되지 않은 항목을 훨씬 더 잘 시각화할 수 있습니다.

하지만! 함정이 있어요


당신은 우리가 끝났다고 생각했습니다.__dict__?

__dict__개체의 메모리 공간을 처리하는 방법이 아니라 방법입니다.

방법이 : 실로다른방있습이다니법제있다습니.__slots__어떻게 작동하는지에 대해서는 여기서 자세히 설명하지 않겠습니다. 더 자세히 알고 싶은지에 대해서는 이미 매우 완벽한 답변이 있습니다.그러나 중요한 것은 슬롯이 정의된 경우:

class C:
    __slots__ = ('foo', 'bar')

    def __init__(self):
        self.foo = 1
        self.bar = 2

>>> c = C()
>>> c.foo
1
>>> c.bar
2
>>> c.__dict__
AttributeError: 'C' object has no attribute '__dict__'

우리는 작별 인사를 할 수 있습니다.__dict__.


그래서 언제 사용해야 합니까?__dict__?

우리가 본 것처럼,__dict__개발자의 자리가 아니라 컴퓨터의 관점에서 봐야 합니다.종종 우리가 우리의 객체의 "속성"이라고 생각하는 것은 실제로 메모리에 저장된 것과 직접적으로 연결되지 않습니다. 속성 또는 특히속사나거용을 __getattr__예를 들어, 그것은 우리의 편안함을 위해 추상화 수준을 추가합니다.

의사에불고구하도용▁of▁use고▁the불.__dict__개체의 속성을 검사하는 것은 대부분의 사소한 경우에 작동합니다. 100% 의존할 수는 없습니다.일반적인 논리를 쓰는 데 사용되는 것은 부끄러운 일입니다.

의 활용 __dict__개체의 메모리 내용을 검사하는 것으로 제한해야 합니다.흔한 일이 아닙니다. 명심하세요.__dict__슬롯을 정의할 때 전혀 정의되지 않거나 메모리에 실제로 저장된 일부 속성이 없을 수 있습니다.

또한 Python의 콘솔에서 클래스의 속성과 메서드를 빠르게 확인하는 것이 매우 유용할 수 있습니다.또는 객체의 속성(우리가 의존할 수 없다고 방금 말한 것은 알지만, 콘솔에서 때때로 실패하거나 정확하지 않은 경우에 관심을 갖는 사람).


고맙지만...그러면 내 개체의 속성을 어떻게 검색합니까?

우리는 그것을 보았습니다.__dict__종종 잘못 사용되어 개체의 속성을 검사하는 데 실제로 의존할 수 없습니다.하지만 그렇다면 올바른 방법은 무엇일까요?개발자의 추상화된 관점에서 객체 속성을 탐색할 수 있는 방법이 있습니까?

네. 자기소개를 하는 방법은 여러 가지가 있는데, 정확한 방법은 여러분이 실제로 무엇을 얻고 싶은지에 따라 달라질 것입니다.인스턴스(instance) 특성, 클래스 특성, 속성, 개인 특성, 짝수 메서드 등...기술적으로 이 모든 것은 속성이며, 상황에 따라 일부는 포함하고 다른 일부는 제외하는 것이 좋습니다.맥락 또한 중요합니다.아마도 당신은 이미 그들의 API를 통해 당신이 원하는 속성을 공개하는 라이브러리를 사용하고 있을 것입니다.

그러나 일반적으로 모듈에 의존할 수 있습니다.

class D:

    foo = 1
    __slots = ('bar', '_baz')

    @property
    def baz(self):
        return self._baz

    @baz.setter
    def baz(self, value):
        self._baz = value

    def __init__(self):
        self.bar = 2
        self.baz = 3

    def pointless_method(self):
        pass


>>> d = D()
>>> import inspect
>>> dict((k, v) for k, v in inspect.getmembers(d) if k[0] != '_')
{
 'bar': 2,
 'baz': 3,
 'foo': 1
}
>>> dict((k, getattr(d, k)) for k, v in inspect.getmembers(D) if inspect.isdatadescriptor(v) or inspect.isfunction(v))
{
 '__init__': <bound method D.__init__ of <__main__.D object at 0x7fb1e26a5b40>>,
 '_baz': 3,
 'bar': 2,
 'baz': 3,
 'pointless_method': <bound method D.pointless_method of <__main__.D object at 0x7fb1e26a5b40>>
}

__filen__는 객체의 인스턴스 변수(데이터 속성)를 사전으로 가져올 수 있습니다.

그래서 만약 있다면,Person아래 클래스:

class Person:
    x1 = "Hello"
    x2 = "World"
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def test1(self):
        pass
        
    @classmethod
    def test2(cls):
        pass
    
    @staticmethod
    def test3():
        pass

obj = Person("John", 27)    
print(obj.__dict__) # Here

__ 사이에 됩니다.name그리고.age다음과 같이 사전에 값을 입력합니다.

{'name': 'John', 'age': 27}

그리고 아래와 같이 인스턴스화 후에 새 인스턴스 변수가 추가되는 경우:

# ...

obj = Person("John", 27)
obj.gender = "Male" # Here
print(obj.__dict__)

__ 사이에 됩니다.name,age그리고.gender다음과 같이 사전에 값을 입력합니다.

{'name': 'John', 'age': 27, 'gender': 'Male'}

또한 아래와 같이 dir()사용하는 경우:

# ...

obj = Person("John", 27)
obj.gender = "Male" 
print(dir(obj)) # Here

아래와 같이 개체의 모든 항목을 목록으로 가져올 수 있습니다.

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__', 
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 
'age', 'gender', 'name', 'test1', 'test2', 'test3', 'x1', 'x2']

그리고 제가 조사한 바로는, 그리고 제가 질문을 한 바로는, Python의 객체에서 정적 또는 특수 변수나 정상, 클래스, 정적 또는 특수 메소드만을 얻을 수 있는 함수는 없습니다.

언급URL : https://stackoverflow.com/questions/19907442/explain-dict-attribute

반응형