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