2017-09-26 61 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