development

파이썬에서 __weakref__는 정확히 무엇입니까?

big-blog 2020. 12. 30. 20:14
반응형

파이썬에서 __weakref__는 정확히 무엇입니까?


놀랍게도에 대한 명시적인 문서가 없습니다 __weakref__. 약한 참조는 여기 에 설명되어 있습니다 . __weakref__의 문서에서도 곧 언급됩니다 __slots__. 그러나 나는 __weakref__그 자체 에 대해 아무것도 찾을 수 없었다 .

정확히 무엇입니까 __weakref__? -플래그 역할을하는 멤버 일뿐 : 존재하는 경우 개체가 약하게 참조 될 수 있습니까? -아니면 원하는 동작을 얻기 위해 재정의 / 할당 할 수있는 함수 / 변수입니까? 어떻게?


__weakref__현재 개체에 대한 모든 약한 참조를 참조하는 불투명 한 개체입니다. 실제로 는 객체에 대한 약한 참조이자 해당 객체에 대한 모든 약한 참조에 대한 이중 연결 목록의 일부인 인스턴스 weakref(또는 때때로 weakproxy)입니다.

가비지 수집기가 참조 대상이 수집되었음을 약한 참조에 알리고 더 이상 기본 포인터에 대한 액세스를 허용하지 않도록하는 구현 세부 사항 일뿐입니다.

약한 참조는 참조하는 객체의 참조 횟수를 확인하는 데 의존 할 수 없습니다. 이는 해당 메모리가 회수되어 현재 다른 개체에서 사용 중일 수 있기 때문입니다. VM이 충돌하는 최상의 시나리오, 최악의 경우 약한 참조가 원래 참조하지 않았던 개체에 대한 액세스를 허용합니다. 이것이 가비지 수집기가 약한 참조에 해당 참조가 더 이상 유효하지 않음을 알려야하는 이유입니다.

구조에 대해서는 weakrefobject.h참조 하고이 개체에 대한 C-API를 참조하십시오 . 그리고 구현 세부 사항은 여기에 있습니다


[편집 1 : 링크드리스트의 성격과 약한 참조가 언제 재사용되는지 설명]

흥미롭게도 공식 문서 는이 주제에 대해 다소 이해하기 어렵습니다.

__weakref__각 인스턴스에 대한 변수가 없으면 정의하는 클래스 __slots__는 해당 인스턴스에 대한 약한 참조를 지원하지 않습니다. 약한 참조 지원이 필요한 __weakref__경우 __slots__선언 의 문자열 시퀀스에 추가 합니다 .

type객체 문서 주제에 너무 많이 따라 도움말 일하지 않는 것 :

유형의 __slots__선언에라는 __weakref__슬롯이 포함 되면 해당 슬롯은 유형 인스턴스의 약한 참조 목록 헤드가되고 슬롯의 오프셋은 유형의 tp_weaklistoffset.

약한 참조는 연결 목록을 형성합니다. 해당 목록의 헤드 (객체에 대한 첫 번째 약한 참조)는를 통해 사용할 수 있습니다 __weakref__. Weakref는 가능할 때마다 재사용되므로 목록 (Python 목록이 아닙니다!)은 일반적으로 비어 있거나 단일 요소를 포함합니다.

:

를 처음 사용할 때 weakref.ref()대상 개체에 대한 새로운 약한 참조 체인을 만듭니다. 이 체인의 헤드는 새로운 weakref이며 대상 객체의 __weakref__:

>>> import weakref
>>> class A(object): pass
>>> a = A()
>>> b = weakref.ref(a)
>>> c = weakref.ref(b)
>>> print(b is c is a.__weakref__)
True

보시다시피, b재사용됩니다. 예를 들어 콜백 매개 변수를 추가하여 파이썬이 새로운 weakref를 생성하도록 강제 할 수 있습니다.

>>> def callback():
>>>   pass
>>> a = A()
>>> b = weakref.ref(a)
>>> c = weakref.ref(b, callback)
>>> print(b is c is a.__weakref__)
False

이제 b is a.__weakref__, c은 체인의 두 번째 참조입니다. 참조 체인은 Python 코드에서 직접 액세스 할 수 없습니다. 체인의 헤드 요소 ( b) 만 볼 수 있지만 체인이 계속되는 방식 ( b-> c)은 볼 수 없습니다.

__weakref__객체에 대한 모든 약한 참조의 내부 링크 목록의 머리도 마찬가지 입니다. 이 역할 __weakref__이 간결하게 설명 된 공식 문서를 찾을 수 없으므로 구현 세부 사항이므로이 동작에 의존해서는 안됩니다.


__weakref__변수는 객체가 약한 참조를 지원 객체 약한 참조를 보존 할 수있게하는 속성이다.

파이썬 문서는 다음과 같이 설명했습니다.

참조에 대한 나머지 참조가 약한 참조 일 때 가비지 수집은 참조를 파괴하고 다른 것에 메모리를 재사용 할 수 있습니다.

따라서 약한 참조의 의무는 객체의 유형과 범위에 관계없이 가비지 수집이 가능하도록 객체에 대한 조건을 제공하는 것입니다.

에 대해 __slots__먼저 문서를 살펴볼 수 있습니다.이 문서는 매우 잘 설명합니다.

기본적으로 클래스 인스턴스에는 속성 저장을위한 사전이 있습니다. 이것은 인스턴스 변수가 거의없는 객체를위한 공간을 낭비합니다. 많은 수의 인스턴스를 생성 할 때 공간 소비가 급증 할 수 있습니다.

기본값은 __slots__클래스 정의에서 정의 하여 재정의 할 수 있습니다 . __slots__선언 각 변수에 대한 값을 유지하도록 각각의 인스턴스 인스턴스 변수 보유 충분한 공간의 시퀀스 걸린다. __dict__각 인스턴스에 대해 생성되지 않기 때문에 공간이 절약 됩니다.

이제 사용하여 이후 __slots__귀하의 속성에 대한 요구 저장 장치를 제어합니다 당신을, 사실의 자동 생성을 방지 __dict__하고 __weakref__각 인스턴스에 대해. __weakref__약한 참조를 처리하기 위해 각 개체의 필수 변수는 무엇 입니까 ?

또한 이러한 모든 문서 외에도 object.__slots__클래스에 대한 내용 은 다음과 같습니다.

이 클래스 변수에는 인스턴스에서 사용하는 변수 이름이있는 문자열, 반복 가능 또는 문자열 시퀀스가 ​​할당 될 수 있습니다. __slots__선언 된 변수를위한 공간을 예약 __dict__하고 __weakref__각 인스턴스에 대한 자동 생성을 방지합니다 .

__slots__, 저장소 할당을 수동으로 관리하기위한 것이며 저장소와 __weakref__관련된 개체에 대한 약한 참조를 허용하는 라이센스 (가비지 수집 기능 때문에)이므로 as __slots__를 제어 할 수 __weakref__있습니다. __dict__속성 을 제어 합니다.

또한 문서는 사용과 함께 약한 참조를 지원하는 객체를 만드는 방법을 보여줍니다 __slots__.

__weakref__각 인스턴스에 대한 변수가 없으면 정의하는 클래스 __slots__는 해당 인스턴스에 대한 약한 참조를 지원하지 않습니다. 약한 참조 지원이 필요한 '__weakref__'경우 __slots__선언 의 문자열 시퀀스에 추가 합니다 .

다음은 Python 3.X의 예입니다.

>>> class Test:
...     __slots__ = ['a', 'b']
... 
>>> 
>>> import weakref
>>> 
>>> t = Test()
>>> 
>>> r = weakref.ref(t)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot create weak reference to 'Test' object
>>> 
>>> class Test:
...     __slots__ = ['a', 'b', '__weakref__']
... 
>>> t = Test()
>>> r = weakref.ref(t)
>>> 
>>> t.__weakref__
<weakref at 0x7f735bc55d68; to 'Test' at 0x7f735bc51fc8>

그러나 python 2.7에서는 문서가 앞서 언급 한 문서와 비슷하지만 이름에 __weakref__변수를 제공하지 않는 인스턴스에서 약한 참조를 만들면 다음이 발생하지 않습니다 .__slots__TypeError

>>> class Test:
...    __slots__ = ['a', 'b']
... 
>>> t = Test()
>>> 
>>> r = weakref.ref(t)
>>> 
>>> r
<weakref at 0x7fe49f4185d0; to 'instance' at 0x7fe4a3e75f80>

참조 URL : https://stackoverflow.com/questions/36787603/what-exactly-is-weakref-in-python

반응형