본 포스팅에서는 sys.modules, __getattr__, __setattr__을 활용하여 모듈의 속성을 다뤄보고자 한다.
sys.modules[__name__]
우선 현재 사용하고 있는 모듈을 객체(object)로 가져와보자.
import sys
now_module = sys.modules[__name__]
print(now_module) # <module '__main__'>
__name__은 파이썬에서 현재 모듈의 이름을 문자열로 반환하는 내장 변수이며, sys.modules[__name__]은 파이썬에서 현재 모듈에 대한 참조이다.
sys.modules dict에 __name__ 값으로 접근하면 현재 모듈의 모듈 객체에 대한 참조를 얻을 수 있다. 이는 모듈의 속성을 추가하거나 수정하거나 모듈 내에서 다른 모듈을 가져오는 등의 목적으로 사용될 수 있으므로 우선 현재 사용하고 있는 모듈을 'now_module'로 선언했다.
getattr
getattr과 setattr은 각각 객체의 속성 값을 가져오고 설정할 수 있게 해주는 파이썬에 내장된 함수이다.
getattr(object, name[, default])은 개체의 명명된 속성 값을 검색하는 데 사용되며, 명명된 특성이 없으면 default 인수에 지정된 값을 반환한다 (기본값이 제공되지 않으면 AttributeError가 발생).
이는 예시를 통해 진행하고자 한다.
getattr(now_module,'np')
"""
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/aidata/lung/WORKSPACE/workspace_s/deep-lung-ln-02_v2/nodulenet/_.ipynb Cell 57 in <cell line: 1>()
----> 1 getattr(now_module,'np’)
AttributeError: module '__main__' has no attribute 'np'
"""
현재 사용하고 있는 모듈에서는 np라는 속성이 선언되지 않아서 오류가 발생한다.
하지만 import numpy as np를 해당 모듈에 선언을 해주어 np라는 속성값을 추가해 주면 잘 인식이 된다.
import numpy as np
getattr(now_module,'np')
"""
<module 'numpy' from '/home/soobumk/.conda/envs/soobumk/lib/python3.9/site-packages/numpy/__init__.py'>
"""
다른 속성값도 추가해서 확인해 보자.
import matplotlib.pyplot as plt
import pandas as pd
getattr(now_module,'plt'), getattr(now_module,'pd')
"""
(<module 'matplotlib.pyplot' from '/home/soobumk/.conda/envs/soobumk/lib/python3.9/site-packages/matplotlib/pyplot.py'>,
<module 'pandas' from '/home/soobumk/.conda/envs/soobumk/lib/python3.9/site-packages/pandas/__init__.py'>)
"""
새롭게 추가된 plt와 pd도 잘 인식이 된다.
getattr과 setattr 활용
setattr(object, name, value)은 개체의 명명된 속성 값을 설정하는 데 사용된다. 명명된 특성이 없는 경우 지정된 이름과 값을 사용하여 새 특성으로 선언이 가능하다.
예를 통해 계산기 모듈을 구성하고 getattr과 setattr을 활용하여 속성값을 변경해 보자.
class Calculation():
def __init__(self,a,b):
self.weight = 10 # 고정된 값
self.a = a
self.b = b
def add(self):
c = (self.a + self.b) * self.weight
return print('Add:', c)
def subtract(self):
d = (self.a - self.b) * self.weight
return print('Subtract:', d)
위와 같이 계산기 모듈을 선언했다. 값을 넣고 인스턴스를 구성한 후에 .add와 .substract 함수를 통해 자동으로 계산이 되는 클래스를 구성했다.
주의 깊게 봐야 하는 건 self.weight가 인스턴스가 생성될 때 default로 10이 입력되어 함수가 작동될 때 자동으로 곱해진다는 것이다.
아래 예시는 2와 5를 입력하여 나온 출력이다.
getattr(now_module,'Calculation') # __main__.Calculation
cal_1 = getattr(now_module,'Calculation')(2,5) # cal_1 = Calculation(2,5)와 동일하다
cal_1.add() # Add: 70
cal_1.subtract() # Subtract: -30
결국 getattr(now_module,'Calculation')(2,5)은 Calculation(2,5)와 동일하며 새로운 인스턴스를 만들어주는 작업이다.
다음 예시는 8과 5를 입력했다.
cal_2 = getattr(now_module,'Calculation')(8,5) # cal_2 = Calculation(8,5)와 동일하다
cal_2.add() # Add: 130
cal_2.subtract() # Subtract: 30
이제 여기서 self.weight 속성값을 setattr를 활용하여 변경해 보자.
cal_1 = getattr(now_module,'Calculation')(2,5)
getattr(cal_1,'a'), getattr(cal_1,'b'), getattr(cal_1,'weight')
# (2, 5, 10)
setattr(cal_1,'weight',100)
getattr(cal_1,'a'), getattr(cal_1,'b'), getattr(cal_1,'weight')
# (2, 5, 100)
cal_1.add() # Add: 700
cal_1.subtract() # Subtract: -300
기본 weight가 10이었다면, setattr를 통해 weight의 속성값을 100으로 변경해 주었다.
이에 따라 자동적으로 10이 아니라 100이 곱해서 값이 바뀌는 걸 확인할 수 있다.
동일하지만 입력값이 다른 같은 예시이다..
cal_2 = Calculation(8,5)
getattr(cal_2,'a'), getattr(cal_2,'b'), getattr(cal_2,'weight')
# (8, 5, 10)
setattr(cal_2,'weight',20)
getattr(cal_2,'a'), getattr(cal_2,'b'), getattr(cal_2,'weight')
# (8, 5, 20)
cal_2.add() # Add: 260
cal_2.subtract() # Subtract: 60
weight가 10에서 20으로 바뀌어 결과도 바뀌었다.
__getattr__을 활용하여 현재 돌아가고 있는 코드 내에서 손쉽게 모듈을 가져와서 새롭게 인스턴스를 선언할 수 있도록 해준다.
또한 __setattr__를 통해 모듈 안의 속성을 바꿔가며 그때마다 인스턴스를 생성할 필요 없이 바꾸고자 하는 속성값만 바꿔가며 모듈을 활용할 수 있다.
'Python' 카테고리의 다른 글
[Python] 여러개의 이미지 한번에 시각화 - matplotlib (0) | 2023.02.18 |
---|---|
[Python] re를 활용하여 문자열을 리스트로 변환하기 (0) | 2023.02.12 |
[Python] try except 활용하여 오류 모아보기 (0) | 2023.02.08 |
[Python] 3D 배열의 Dice score 코드 만들기 (segmentation 평가) (0) | 2023.01.09 |
[Python] Dice score 코드 만들기 (segmentation 평가) (0) | 2023.01.09 |
댓글