python object의 멤버 attribute를 런타임에 생성하기

Python 2008. 3. 20. 00:15
python을 사용하여 프로그램을 작성하다보면 class를 정의하여 사용하게 되는 경우가 많이 있습니다.
class의 인스턴스로서 만들어진 object는 class에서 정의하고 있는 attribute를 가지고 있습니다. 그런데, 스크립트 실행 도중에 class에 정의되어 있지 않은 attribute를 정의하고 싶을 때가 있습니다.

이 기능을 구현해둔 예가 optparse.Values 라는 class입니다.

import optparse
v = optparse.Values()
v.a=1
print v.a

이 코드가 문제없이 실행되고 1을 찍습니다.

파이썬에는 역시 dict라고 하는 dictionary 또는 map이라고 불리는 기본 데이터타입이 있습니다.
key-value의 쌍을 모아둔 데이터입니다.

d = {'a' : 1, 'b' : 2}
print d['a'], d['b']

위와같이 정의하고 사용합니다.
또는,

d={}
d['a'] = 1
d['b'] = 2
print d['a'], d['b']

이렇게 정의해도 결과는 같습니다.

별것 아닌거 같아 보이는 이런 사용 방법이 매우 편리할 때가 있습니다.
어떤 값들이 저장될지가 코딩타임에 결정하기 어려운 경우죠..
위의 두 가지 경우가 별로 유용한 예로서 대표적인게 윈도우에서 흔히보는 RFC822스타일의 *.ini 설정파일입니다.
# comment
[section]
key = value
key: value

위와같은 형식으로 작성되는데, 이 설정파일을 객체화하여 사용하기 위해서는 위의 기능이 참으로 아쉬워집니다.

[mysqld]
log-bin = /var/log/mysql/binlog

위는 mysql설정파일인 my.cnf의 일부분입니다. mysql의 설정에 따라 적절히 행동하는 프로그램을 만들고자 할 때에, 이 설정파일을 읽어서 객체화하여,
if conf_mysql.mysqld.log_bin.startswith("/var/log"):
    os._exit(1)

이런걸 만든다고 하면 정말이지 아쉬운 기능입니다.
이밖에도 예는 많이 있을 겁니다.(생각은 딱히 안납니다만..ㅎㅎ;;;)

저의 경우에 이런 용도로 사용되는 클래스를 많이 설계하게되다보니, 위 두가지가 모두 가능한 클래스를 만들어 씁니다. BaseObject라는 class에 위 기능을 구현해 두고 필요할때 상속해서 사용하면 됩니다.
사용예

사용예. 변수나 함수 모두 이미 만들어진 객체에 추가해 줄 수 있습니다.

pydoc결과

pydoc결과 예시


BaseObject의 doctest 결과

BaseObject의 doctest 결과


MyObject의 doctest 결과

MyObject의 doctest 결과


위 예제에 보여진 두개의 간단한 코드를 첨부합니다.

: