2017-09-26 90 views
1

在python(3)我想从几个基类动态地创建一个派生类。如何动态选择python基类?

具体的例子:在selenium,为了运行基于GUI测试,您可以通过以下方式启动从例如Firefox或Chrome司机:

driver = webdriver.Firefox() 
driver = webdriver.Chrome() 

现在我想创建一个派生类,其额外的功能被添加。喜欢的东西

class MyDriver(webdriver.Firefox): 
    def find_button_and_click_on_it_no_matter_what(self, params): 
     ... 

但基类的既可以是firefox驱动程序或铬driver。我发现相关here的东西,但它似乎并没有工作:

class MyDriver(object): 
    def __new__(cls, base_type, *args, **kwargs): 
     return super(HBPDriver, cls).__new__(base_type, *args, **kwargs) 

    def __init__(self): 
     pass 

调用此命令

driver = mydriver.MyDriver(webdriver.Firefox())  

给出了一个错误

TypeError: object.__new__(X): X is not a type object (WebDriver) 

如何做是正确的?以及如何在派生类上调用__init__ ...?

我希望这是清楚,我想达到什么样的...

回答

2

到时候你拨打__new__为时已晚选择该类实例; __new__是该类的属性。相反,你需要一个简单的工厂函数:

def my_driver(cls, *args, **kwargs): 
    class NewThing(cls): 
     ... 
    return NewThing(*args, **kwargs) 

ff = my_driver(webdriver.Firefox) 

另一种选择是使用表达式定义的基类:

if ...: 
    base = webdriver.Firefox 
elif ...: 
    base = webdriver.Chrome 
class MyDriver(base): 
    ... 

第三种选择是跳过class声明并直接使用type,虽然我除非班级声明的主体将是空的,否则不会推荐这一点。

class MyDriver(base): 
    pass 

相当于MyDriver = type('MyDriver', (base,), {})

+0

坦克的选项 - 但在哪里/如何在第一个选项中定义附加的类方法? – Alex

+0

第一个选项在一定程度上是另外两个的包装(除了没有定义子类,但实例化了对象)。我已经更新了它,以显示它如何使用与第二个示例相同的想法在函数中本地定义一个新类。 – chepner

+0

啊我明白你的意思了。我会说这些是同样的做法。无论如何,你的建议似乎工作... – Alex