2016-11-16 79 views
1

我的Python程序中有一个相当复杂的类层次结构。该程序有许多工具,它们是模拟器或编译器。这两种方法有一些共同的方法,所以有一个Shared类作为所有类的基类。的条向下的例子如下所示:我可以在Python中为继承的方法创建别名吗?

class Shared: 
    __TOOL__ = None 

    def _Prepare(self): 
    print("Preparing {0}".format(self.__TOOL__)) 


class Compiler(Shared): 
    def _Prepare(self): 
    print("do stuff 1") 
    super()._Prepare() 
    print("do stuff 2") 

    def _PrepareCompiler(self): 
    print("do stuff 3") 
    self._Prepare() 
    print("do stuff 4") 


class Simulator(Shared): 
    def _PrepareSimulator(self): # <=== how to create an alias here? 
    self._Prepare()   


class Tool1(Simulator): 
    __TOOL__ = "Tool1" 

    def __init__(self): 
    self._PrepareSimulator() 

    def _PrepareSimulator(self): 
    print("do stuff a") 
    super()._PrepareSimulator() 
    print("do stuff b") 

能否定义方法Simulator._PrepareSimulator作为别名到Simulator/Shared._Prepare

我知道我可以创建本地别名,如:__str__ = __repr__,但在我的情况下,_Prepare在上下文中是未知的。我没有self也没有cls引用此方法。

我可以写一个装饰器来返回_Prepare而不是_PrepareSimulator?但是,如何在装饰器中找到_Prepare

我是否需要调整方法绑定呢?

+2

你可以将'_PrepareSimulation'定义为'Shared._Prepare'的别名,即:'_PrepareSimulation = Shared._Prepare'。但我完全不知道为什么你想要。你究竟在努力实现什么? –

+0

你有'_PrepareSimulation'和'_PrepareSimulator' - 是不同的还是一个错字? – tdelaney

+0

错字:)更高级别的类可以覆盖方法,并根据需要插入它们的逻辑。大多数类都使用基类的功能 – Paebbels

回答

1

我设法创建了一个基于装饰者的解决方案,它确保了类型安全。第一个装饰器将一个别名注释到本地方法。需要确保别名目标的安全。需要使用第二个装饰器来替换Alias实例,并检查别名是否指向类型层次结构中的方法。

装饰/别名定义:

from inspect import getmro 

class Alias: 
    def __init__(self, method): 
    self.method = method 

    def __call__(self, func): 
    return self 

def HasAliases(cls): 
    def _inspect(memberName, target): 
    for base in getmro(cls): 
     if target.__name__ in base.__dict__: 
     if (target is base.__dict__[target.__name__]): 
      setattr(cls, memberName, target) 
      return 
     else: 
     raise NameError("Alias references a method '{0}', which is not part of the class hierarchy: {1}.".format(
      target.__name__, " -> ".join([base.__name__ for base in getmro(cls)]) 
     )) 

    for memberName, alias in cls.__dict__.items(): 
    if isinstance(alias, Alias): 
     _inspect(memberName, alias.method) 

    return cls 

用例:

class Shared: 
    __TOOL__ = None 

    def _Prepare(self): 
    print("Preparing {0}".format(self.__TOOL__)) 


class Shared2: 
    __TOOL__ = None 

    def _Prepare(self): 
    print("Preparing {0}".format(self.__TOOL__)) 


class Compiler(Shared): 
    def _Prepare(self): 
    print("do stuff 1") 
    super()._Prepare() 
    print("do stuff 2") 

    def _PrepareCompiler(self): 
    print("do stuff 3") 
    self._Prepare() 
    print("do stuff 4") 


@HasAliases 
class Simulator(Shared): 
    @Alias(Shared._Prepare) 
    def _PrepareSimulatorForLinux(self): pass 

    @Alias(Shared._Prepare) 
    def _PrepareSimulatorForWindows(self): pass 


class Tool1(Simulator): 
    __TOOL__ = "Tool1" 

    def __init__(self): 
    self._PrepareSimulator() 

    def _PrepareSimulator(self): 
    print("do stuff a") 
    super()._PrepareSimulatorForLinux() 
    print("do stuff b") 
    super()._PrepareSimulatorForWindows() 
    print("do stuff c") 

t = Tool1() 

设置@Alias(Shared._Prepare)@Alias(Shared2._Prepare)将引发异常:

NameError: Alias references a method '_Prepare', which is not part of the class hierarchy: Simulator -> Shared -> object.

相关问题