2

この質問に答える私の試みは、次の質問に基づいています:基本クラスを派生クラス python にキャストする (またはクラスを拡張するより pythonic な方法)

別のモジュールから返されるオブジェクトに機能を追加する mixin クラスを作成しています。他のモジュールのコードは次のようになります。

class Foo(Mixin):
    def __new__(cls, *args, **kwargs):
        #...handle a bunch of cases

        if case1:
            return FooTypeA
        elif case2:
            return FooTypeB
        #... etc

class FooTypeA(Mixin):
    #...

class FooTypeB(Mixin):
    #...

MyMixin を作成しました。これは、Foo によって返されるオブジェクトに機能を少し追加したものです。問題を解決するための私の試みはこれです:

from other_module import Foo, FooTypeA, FooTypeB, ...

class MyFoo(Foo):
    def __new__(cls, *args, **kwargs):
        #...handle most of the same cases

        if case1:
            ret = FooTypeA(*args, **kwargs)
            ret.__class__ = MyFooTypeA
        if case2:
            ret = FooTypeB(*args, **kwargs)
            ret.__class__ = MyFooTypeB
        #... etc


class MyFooTypeA(FooTypeA, MyMixin):
    pass

class MyFooTypeB(FooTypeB, MyMixin):
    pass

これは本当に、本当に醜く見えます。本当に良い解決策はありませんか?

そうでない場合、なぜですか?

編集:詳細に立ち入らずに簡単になると思いましたが、実際に取り組んでいるコードはhereです。このモジュールの作成者は「WebDriverMixin」を作成しました。これは主に、セレン Web ドライバーのインスタンスが存在するページ上の要素にアクセスするための優れた構文を提供します。私がテストしている特定のサイトの要素にアクセスするためのより良い構文を提供する「SiteSpecificMixin」があります。

webdriverplus.WebDriverwebdriverplus.Firefoxwebdriverplus.Chromewebdriverplus.Ieなどのインスタンスを返します。 and から継承し、 andからwebdriverplus.Firefox継承します。webdriverplus.WebDriverMixinselenium.webdriver.firefox.webdriver.Firefoxwebdriverplus.Chromewebdriverplus.WebDriverMixinselenium.webdriver.firefox.webdriver.Chrome

返されるオブジェクトに機能を追加したいのですがwebdriverplus.Webdriver、クラスを作成し、 の本体をmysite.SiteSpecificDriverにコピーして貼り付けてから、 ( andから継承する必要があります)、( andから継承する必要があります) を書く必要があるようです。など、元の作成者が自分で処理する自分のモジュール内のすべてのブラウザーを再処理します。webdriverplus.WebDriver.__new__mysite.SiteSpecificDriver.__new__mysite.Firefoxwebdriverplus.Firefoxmysite.SiteSpecificMixinmysite.Chromewebdriverplus.Chromemysite.SiteSpecificMixin

上記の例のようなコードで処理していますが、うまくいきます。私は OOP を初めて使用しますが、OO 手法についての私の理解では、オブジェクトの種類に依存する長い if-elif-...-else 句を含むコードを回避できるはずです。だから私は何か間違ったことをしているに違いないと思います。

4

1 に答える 1

1

これをより動的な方法で書き直すことができます。

from other_module import Foo, FooTypeA, FooTypeB

bases = [Foo, FooTypeA, FooTypeB]

class MyMixin(object):
    pass

def factory(bases, mixins, name='MyClass'):
    return type(name, bases + mixins, {})

new_classes = [factory((c,), (MyMixin,)) for c in bases]
于 2013-08-17T14:14:14.400 に答える