| python 에서는 다중상속이라는 편리한 기능이 있지만 그 때문에 골치아픈 경우가 발생합니다. 그를 피할 수 있는 방법이 MIX-IN 입니다.😊
-> 이 경우, code duplicate가 일어남
공통된 함수를 M이라는 mixin class 안에 정의함
자식 클래스가 사용할 METHOD 몇개만 정의하는 클래스(attribute X)
attribute 없으므로 init method(constructor)도 필요없음
믹스인 클래스를 작성해두면 여러 클래스에 적용 가능함!(Generic)
class A:
total = 345
class B(A):
pass
class C(A):
pass
# locked packages so far.
class M:
def print_total(self):
print(self.total)
class D(B,M):
pass
class E(C,M):
pass
e = E()
e.print_total()
ToDictMixin
클래스 정의class ToDictMixin:
def to_dict(self):
return self._traverse_dict(self.__dict__)
def _traverse_dict(self, instance_dict):
output = {}
for key, value in instance_dict.items():
output[key] = self._traverse(key, value)
return output
# [Bool] = isinstance(확인하고자 하는 데이터 값, 확인하고자 하는 데이터 타입)
def _traverse(self, key, value):
if isinstance(value, ToDictMixin):
return value.to_dict()
if isinstance(value, dict):
return self._traverse_dict(value)
if isinstance(value, list):
return [self._traverse(key, i) for i in value]
elif hasattr(value, '__dict__'):
return self._traverse_dict(value.__dict__)
else:
return value
to_dict()
class BinaryTree(ToDictMixin): # mixin class 상속
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
tree = BinaryTree(10,
left = BinaryTree(7, right=BinaryTree(9)),
right = BinaryTree(13, left=BinaryTree(11))
)
print(tree.to_dict())
>>>{'value': 10, 'left': {'value': 7, 'left': None, 'right': {'value': 9, 'left': None, 'right': None}}, 'right': {'value': 13, 'left': {'value': 11, 'left': None, 'right': None}, 'right': None}}
다음은 parent attribute가 추가된 클래스
BinaryTreeWithParent
class BinaryTreeWithParent(BinaryTree):
def __init__(self, value, left=None, right=None, parent=None):
super().__init__(value, left=left, right=right) #BinaryTree로부터 값 상속
self.parent = parent
## overrriding 으로 순환 참조(무한루프)를 막음 -> to_dict() 사용가능
def _traverse(self,key,value):
if isinstance(value, BinaryTreeWithParent) and key=='parent':
return value.value
else:
return super()._traverse(key,value)
root = BinaryTreeWithParent(10)
root.left = BinaryTreeWithParent(7, parent=root)
root.left.right = BinaryTreeWithParent(9, parent=root.left)
print(root.to_dict())
>>> {'value': 10, 'left': {'value': 7, 'left': None, 'right': {'value': 9, 'left': None, 'right': None, 'parent': 7}, 'parent': 10}, 'right': None, 'parent': None}
BinaryTreeWithParent
를 애트리뷰트로 저장하는 모든 클래스도 자동으로 ToDictMixin
을 문제없이 사용하게 됨:class NamedSubTree(ToDictMixin):
def __init__(self, name, tree_with_parent):
self.name = name
self.tree_with_parent = tree_with_parent
my_tree = NamedSubTree('foobar', root.left.right)
print(my_tree.to_dict())
>>> {'name': 'foobar', 'tree_with_parent': {'value': 9, 'left': None, 'right': None, 'parent': 7}}
def add(a,b):
return a + b
integer, list, str 등 다양한 자료형에 적용가능!import pickle
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
self.area = width * height
rect = Rectangle(10, 20)
# 사각형 rect 객체를 직렬화 (Serialization)
with open('rect.data', 'wb') as f:
pickle.dump(rect, f)
# 역직렬화 (Deserialization)
with open('rect.data', 'rb') as f:
r = pickle.load(f)
print("%d x %d" % (r.width, r.height))