티스토리 뷰

Python

Python,module weakref [약한참조]

hwangyoungjae 2016. 5. 20. 21:53
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

어떤 객체가 생성되면 메모리에 저장되고지정된 이름을 참조하여 접근한다메모리상의 동일한 객체에 대해서 여러 다른 이름으로 참조가 가능하고참조되는 이름이 증가할때마다 내부적으로 참조카운터가 하나씩 증가한다또한 이렇게 증가한 참조카운터는 더이상 그 변수가 사용하지 않게 되면내부적으로 참조카운터가 하나씩 감소한다참조카운터가 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을 반환

 

 

참조 : 빠르게 활용하는 파이썬프로그래밍

'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
링크
«   2024/07   »
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
글 보관함