Doge log

Abby CTO 雑賀 力王のオフィシャルサイトです

局所的にクラスを拡張する

withを使ってなにか出来ないかずっと考えてたんだけどありきたりなアイディアしか浮かばなかった。
でもあまりwithをどうこうっていうのを書いてる人もいなかったので書いておく。
with句のブロック間のみクラスを拡張する。

from contextlib import contextmanager

@contextmanager
def mixin(cls, mixcls):
    bases = cls.__bases__
    try:
        cls.__bases__ += (mixcls,)
        yield cls
    finally:
        cls.__bases__ = bases
        
class A():
    
    def test(self):
        print("is A")

class B():
    
    def spam(self):
        print("is B")

a = A()
a.test()
#a.spam() #=> AttributeError

#この間のみ拡張する
with mixin(A, B):
    b = A()
    a.spam()
    b.spam()

b.spam() # => AttributeError

with句の間はクラスAでクラスBのメソッドを呼び出せるようになる。
拡張されっぱなしを防ぐ。
既存のインスタンスにも拡張が適用される。
実際あまりこういうのを使わないといけないケースは少ない。