티스토리 뷰
어떤 객체가 생성되면 메모리에 저장되고, 지정된 이름을 참조하여 접근한다. 메모리상의 동일한 객체에 대해서 여러 다른 이름으로 참조가 가능하고, 참조되는 이름이 증가할때마다 내부적으로 참조카운터가 하나씩 증가한다. 또한 이렇게 증가한 참조카운터는 더이상 그 변수가 사용하지 않게 되면, 내부적으로 참조카운터가 하나씩 감소한다. 참조카운터가 0보다 큰 경우, 즉 1개이상 변수가 이를 사용하고 있는 경우에는 가비지컬렉션(사용하지 않는 메모리반환)이 일어나지 않는다.
weakref모듈은 객체에 대한 약한 참조(Weak reference)를 만드는데 사용한다.
약한참조는 변수가 객체를 참조할때, 참조카운터를 증가시키지 않고 참조하는 객체를 얻을수 있다. 예를 들어 C와 연동하는 경우, 순환참조가 발생할수 있으며 이는 사라지지 않는 객체들이 존재할수 있는 위험이 있다. 이러한 경우 약한 참조객체를 사용하면 순환참조를 막을수 있다.
>> 주요함수 <<
함수 | 내용 |
class weakref.ref(object[, callback]) | 객체에 대한 약한 참조 객체를 반환. 객체가 메모리에 존재하는 경우 객체에 대한 참조를 반환하며, 그렇지 않은 경우 None을 반환 |
weakref.proxy(object[, callback]) | 객체에 대한 약한 참조 프록시를 생성, 명시적으로 약한 참조 객체를 생성하는 대신에 프록시를 이용하여 객체으 참조를 얻을수 있음 |
weakref.getweakrefcount(object) | 객체에 대한 약한 참조 카운터를 반환 |
weakref.getweakrefs(object) | 객체를 참조하는 약한 참조 객체와 프록시를 리스트로 반환 |
아래 예제는 약한 참조 객체를 생성하여 그에 대한 참조를 변수에 할당하는 예제이다.
이렇게 얻은 변수는 원본객체와 동일한 메모리공간을 가리킨다.
더 이상 원본객체에 대해서 참조하는 값이 없는 경우 참조객체는 None을 반환한다.
>>> import weakref >>> class Apple: pass
>>> a=Apple() >>> a.color='red' >>> r=weakref.ref(a) #약한 참조 객체 생성 >>> ref_a=r() #원본 객체의 참조 생성 >>> a.color #두 값이 동일하며 같은 객체를 나타냄 'red' >>> ref_a.color 'red' >>> a is ref_a #두객체는 동일 True >>> r <weakref at 01041540; to 'Apple' at 00BB09D0> >>> del a,ref_a #참조하는 변수 삭제 >>> r() #원본객체가 삭제되면 None을 반환함 >>> |
아래는 약한 참조 객체 대신에 프록시를 생성하여 사용하는 예이다.
프록시객체는 원본객체를 잠시 대신하는것으로, 원본객체와 동일한 메모리공간을 나타내느것은 아니다. 또한 원보낵체가 사라지게 되면, 프록시 역시 None이 되어 더이상 사용이 불가능하다.
>>> import weakref >>> class Apple: pass
>>> a=Apple() >>> a.color='red' >>> proxy_a=weakref.proxy(a) #프록시 객체 생성 >>> a.color 'red' >>> proxy_a.color #프록시를 통하여 원본 객체 참조가능 'red' >>> a is proxy_a #원본객체와 프록시는 다름 False >>> a <__main__.Apple object at 0x00BB09D0> >>> proxy_a <weakproxy at 01041540 to Apple at 00BB09D0> >>> del a >>> proxy_a <weakproxy at 01041540 to NoneType at 1E1E08F4> |
마지막으로 객체에 대한 약한 참조 갯수와 약한 참조 리스트를 구하는 예이다.
>>> a=Apple() >>> r=weakref.ref(a) >>> proxy_a=weakref.proxy(a) >>> weakref.getweakrefcount(a) #약한 참조 갯수 2 >>> weakref.getweakrefs(a) #약한 참조 리스트 [<weakref at 010417B0; to 'Apple' at 00BB09D0>, <weakproxy at 01041750 to Apple at 00BB09D0>] |
※ 모든 객체가 약한 참조 객체를 생성할수 있는것은 아니다.
현재 지원 가능한 객체는 클래스 인스턴스, 파이썬 함수, 인스턴스메서드, sets, frozensets, 파일객체, 생성자, 타입객체, bsddb모듈의 DBCursor, 소켓, arrays, dequeue, 정규식 패턴 객체이다. |
만약 리스트, 사전같은 내장타입에 대하여 약한 참조 객체를 하고자 하는 경우 서브클래싱(subclassing)을 이용하여 구현할수 있다.
>>> import weakref >>> class MyDict(dict): #사전을 상속받은 클래스 생성 pass
>>> mydict=MyDict() >>> mydict['apple']=100 >>> mydict['orange']=300 >>> mydict {'orange': 300, 'apple': 100} >>> proxy_dict=weakref.proxy(mydict) #프록시 객체 생성 >>> proxy_dict <weakproxy at 01059150 to MyDict at 00F7F1F8> >>> proxy_dict['apple'] #해당 값의 참조 가능 100 >>> del mydict >>> proxy_dict #원본객체 소멸시 프록시는 None이 됨 <weakproxy at 01059150 to NoneType at 1E1E08F4> |
>> 약한 사전 <<
약한사전(Weak dictionary)은 구성요소인 키(Key)와 값(Value)중 하나가 약한 참조로 이루어져 있는 경우이다. 예를 들어 각 개체에 ID를 키로 부여하여 사전에 넣어서 관리하는 경우, 사전에 넣는 순간 벌써 참조카운터가 하나 증가한다. 반면에 약한 사전의 경우 사용자가 사전에 입력을 해도 참조카운터가 증가되지 않으며, 원본객체가 삭제되면 자동적으로 사전의 객체도 삭제되어 None이 된다.
함수 | 설명 |
class weakref.WeakKeyDictionary([dict]) | 키를 약한 참조로 갖는 사전객체를 생성 |
class weakref.WeakValueDictionary([dict]) | 값을 약한 참조로 갖는 사전객체를 생성 |
예제는 위에서 설명한 각 객체에 ID를 부여하여 사전으로 관리하는 코드를 예로 설명하였다.
아래의 ObjectManager클래스는 객체를 입력받고 키를 반환하는 InputObject()메서드와 키를 입력하면 해당 객체를 반환하는 GetObject()메서드가 있다. 만약 원본 객체가 메모리에서 삭제되면, ObjectManager는 해당 키에 대한 반환값으로 None을 반환한다.
import weakref class ObjectManager: def __init__(self): self.weakDict=weakref.WeakValueDictionary()
def InputObject(self, obj): objectID=id(obj) #입력받은 객체의 ID생성 self.weakDict[objectID]=obj #약한 사전의 값으로 입력 return objectID
def GetObject(self, objectID): try: return self.weakDict[objectID] #객체가 존재하는 경우 반환
except: return None #객체가 소멸된 경우 None반환 |
실행
>>> class Apple: pass
>>> red_apple=Apple() #관리할 객체 >>> red_apple.color='red' >>> objectmanager=ObjectManager() #ObjectManager생성 >>> red_id=objectmanager.InputObject(red_apple) #객체를 입력하고 ID를 받음 >>> red_apple.color 'red' >>> objectmanager.GetObject(red_id).color #발급받은 ID로 원본 객체 참조 가능 'red' >>> del red_apple #원본 객체 삭제 >>> objectmanager.GetObject(red_id) #ObjectManager에서도 None을 반환 |
참조 : 빠르게 활용하는 파이썬3 프로그래밍
'Python' 카테고리의 다른 글
Python, str(), repr(), ascii(),eval() (0) | 2016.05.24 |
---|---|
Python, XML사용하기 (0) | 2016.05.20 |
Python,module queue (0) | 2016.05.20 |
Python,module threading [멀티스레드] (0) | 2016.05.19 |
Python, 데이터베이스의 사용 (0) | 2016.05.19 |
- Total
- Today
- Yesterday
- Java
- vba
- activebackground
- ManyToOne
- borderwidth
- highlightbackground
- Python
- checkbutton
- tkinter command & bind [명령어묶기와 사건묶기] Python
- Private
- 상수
- Excel
- IdClass
- 폼
- highlightthickness
- Module
- fetch join
- onetomany
- apache
- 리눅스
- Linux
- activeforeground
- indicatoron
- tkinter
- disabledforeground
- JPA
- 파이썬
- command
- Composite Key
- FetchType
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |