我尝试回答此问题的尝试是基于以下问题:Cast base class to derived class python (or more pythonic way of extending 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”,其中大部分提供了一些更好的语法来访问硒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]
关于python - 将行为添加到外部模块返回的对象的pythonic方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18288731/