2016-11-16 41 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.

相關問題