2
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

pythonでtraitみたいなこと

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
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
2
Help us understand the problem. What are the problem?