2013-07-11 88 views
31

我的Python知識是有限的,我需要一些幫助下面的情況。動態選擇繼承類從

假設我有兩個類AB,是否有可能在Python做類似如下(概念):

import os 
if os.name == 'nt': 
    class newClass(A): 
     # class body 
else: 
    class newClass(B): 
     # class body 

所以問題是,我想創建一個類newClass這樣它會基於平臺差異從不同的基類繼承,這是可以在Python中做到的嗎? 謝謝。

回答

55

您可以使用conditional expression

class newClass(A if os.name == 'nt' else B): 
    ... 
+2

+1打我吧。 ;) –

+1

所以......美麗。 – corazza

+9

女士們,先生們,讓我們來聽聽Python。 –

12

是的,你可以做你寫什麼。雖然就個人而言,我可能會做這種方式的清潔度:

class _newClassNT(A): 
    # class body 

class _newClassOther(B): 
    # class body 

newClass = _newClassNT if os.name == 'nt' else _newClassOther 

這是假設你需要的類體中真正做不同的事情實現明智的。如果您需要更改繼承,你可以嵌入if聲明右邊有:

class newClass(A if os.name == 'nt' else B): 
    # class body 
+0

非常感謝您的幫助! – taocp

+0

爲什麼要這樣做,而不是根據條件將'A或B分配給'BaseCls'然後'class newClass(BaseCls)'? – cowbert

4

從Java和C#世界的到來,做這樣的事情的想法讓我畏縮= P。 (不是說有條件地繼承一個類的想法很糟糕 - 我只是不習慣它。)

考慮一下,如果這個問題是關於Java的話,我會這樣做。我張貼的模式 - 實現一個接口,然後用一個工廠的實現之間進行選擇 - 以提供另一個角度想問題:

public interface OsDependent { 
    public void doOsDependentStuff(); 
} 

public class WindowsDependentComponent implements OsDependent { 
    @Override 
    public void doOsDependentStuff() { 
    //snip 
    } 
} 

public class AppleDependentComponent implements OsDependent { 
    @Override 
    public void doOsDependentStuff() { 
    //snip 
    } 
} 

public class OsDependentComponentFactory { 
    public OsDependent getOsDependentComponent(Platform platform) { 
    if(platform == Platform.WINDOWS) 
     return new WindowsDependentComponent(); 
    else if(platform == Platform.APPLE) 
     return new AppleDependentComponent(); 
    else 
     return null; 
    } 
} 

肯定有很多更多的代碼,但它是在一個合適的解決方案一個強類型的環境。


編輯:一個顯著差異我我的答案和原題之間注意到:

如果你有條件地從多個不同的類繼承,那麼超包含取決於你使用的操作系統代碼,而從它們繼承的類包含所有操作系統相同的代碼。繼承鏈的頂部與操作系統有關;底部不是。

我的方法是另一種方式。接口(或超類)定義了所有平臺類似的方法,而不同的實現(或子類)具有與操作系統相關的代碼。繼承鏈的頂端是操作系統不可知的。

+0

我一定會喜歡這個(轉換爲python)或亨利凱特的解決方案。雖然arshajii的人很好,很簡單,但它只能處理兩種不同的操作系統類型,所以它不是「未來的安全」,正如Robert C. Martin在他的精彩書籍(Clean Code)中指出的那樣,最好是安全,然後抱歉。 Python在太多不同的平臺上運行以忽略這個事實... – tamasgal

2

當你有兩個以上的選項可供選擇時,我已經找到了自己動態繼承類的方法。我確信其他人在我之前使用過這個,但是我在網上找不到這樣的東西,所以我認爲我應該與你分享。

class A(): 
    # Class A Body 
class B(): 
    # Class B Body 
class C(): 
    # Class C Body 
class D(): 
    # Class D Body 
def MakeObject(InheritedClassName): # InheritedClassName is a string 
    def CheckClass(InheritedClass): 
     if InheritedClass == "A": 
      return A 
     elif InheritedClass == "B": 
      return B 
     elif InheritedClass == "C": 
      return C 
     else: 
      return D 
    class WantedClass(CheckClass(InheritedClassName)): 
     # WantedClass Body 
    YourObject = WantedClass() 
    return YourObject 
CreateObject = MakeObject(str(input("Chose A, B, C or D"))) 

這段代碼可以被修改,你可以完全配合它。這是我最喜歡設置動態類繼承的方式,儘管它有點長,因爲您可以根據需要選擇多個選項,甚至可以爲每個對象具有多個動態選擇的繼承。

1

對於那些在使用不同模塊時有類似需求的人。 首先,創建一個文件switcher.py並把它裏面的下列

class Switcher(): 
    def choose(clname): 
     Switcher.clname = clname 

接下來,在你的newClass.py

import switcher 

class newClass(switcher.Switcher.clname): 
    ... 

最後,在主腳本

import switcher 
import os 
    if os.name == 'nt': 
     switcher.Switcher.choose(A): 
    else: 
     switcher.Switcher.choose(B): 

# that's the moment you're creating class with desired inheritance 
import newClass.newClass