2013-07-11 42 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