Skip to main content
 首页 » 编程设计

python之将行为添加到外部模块返回的对象的 pythonic 方法是什么

2025年05月04日9freeliver54

我试图回答这个问题是基于这个问题: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]