Overview
ruby の extend
みたいな感じにやりたい話。
$ python -V
Python 3.7.2
振る舞いだけ別で定義して後から mixin みたいなことは、言語の機能としてはできないっぽいけど、
type
でその場で class 生成して、対象の __class__
に設定すると動的多重継承みたいにできるらしい。
委譲で済むならその方が良いと思うけど。
a.py
class TraitA:
def m1(self):
print(self, "m1")
def m2(self):
print(self, "m2")
class TraitB:
def m1(self):
print(self, "m1")
def m2(self):
print(self, "m2")
class Base:
@classmethod
def factory(cls, val):
x = cls(val)
if val == "A":
trait = TraitA
else:
trait = TraitB
x.__class__ = type("{}+{}".format(cls.__name__, trait.__name__), (cls, trait), {})
return x
def __init__(self, val):
self.val = val
def __repr__(self):
return "<{}>\t{}".format(self.__class__.__name__, str(self.__dict__))
def is_A(self):
return isinstance(self, TraitA)
def is_B(self):
return isinstance(self, TraitB)
if __name__ == "__main__":
a = Base.factory("A")
a.m1()
a.m2()
print(a.is_A())
print(a.is_B())
print("-"*30)
b = Base.factory("B")
b.m1()
b.m2()
print(b.is_A())
print(b.is_B())
実行
$ python a.py
<Base+TraitA> {'val': 'A'} m1
<Base+TraitA> {'val': 'A'} m2
True
False
------------------------------
<Base+TraitB> {'val': 'B'} m1
<Base+TraitB> {'val': 'B'} m2
False
True