我回答这个问题的尝试借鉴了这个问题:Cast base class to derived class python (or more pythonic way of extends classes)
我正在编写一个 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”,它主要提供了一些更好的语法来访问硒网络驱动程序实例所在的页面上的元素。我有“SiteSpecificMixin”,它提供了一些更好的语法来访问我正在测试的特定站点的元素。
webdriverplus.WebDriver
webdriverplus.Firefox
返回, webdriverplus.Chrome
,webdriverplus.Ie
等的实例。webdriverplus.Firefox
继承自webdriverplus.WebDriverMixin
and selenium.webdriver.firefox.webdriver.Firefox
,webdriverplus.Chrome
继承自webdriverplus.WebDriverMixin
andselenium.webdriver.firefox.webdriver.Chrome
等。
我想为返回的对象添加功能webdriverplus.Webdriver
,这似乎需要创建一个类,mysite.SiteSpecificDriver
复制+粘贴的主体webdriverplus.WebDriver.__new__
into mysite.SiteSpecificDriver.__new__
,然后编写mysite.Firefox
(需要从webdriverplus.Firefox
and继承mysite.SiteSpecificMixin
),mysite.Chrome
(需要从webdriverplus.Chrome
and继承mysite.SiteSpecificMixin
),等等,并重新处理我自己的模块中的所有浏览器,这些浏览器是原作者在他的模块中处理的。
我现在正在使用上面示例中的代码处理它,并且它可以工作。我是 OOP 新手,但我对 OO 技术的理解是,它们应该让您避免使用长 if-elif-...-else 子句的代码,这些子句取决于您使用的对象类型,所以我认为我一定做错了什么。