2016-11-16 4 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/Shared._Prepareへの別名として方法Simulator._PrepareSimulatorを定義することはできますか?

私は__str__ = __repr__のようなローカルエイリアスを作成できますが、私のケースでは_Prepareはコンテキストではわかりません。私はselfclsもありません。

_PrepareSimulatorの代わりに_Prepareを返すデコレータを書くことができますか?しかし、私はどのようにして_Prepareをデコレータで見つけることができますか?

メソッドバインディングも調整する必要がありますか?

+2

ます'_PrepareSimulation'を' Shared._Prepare'のエイリアスとして定義することができます: '_PrepareSimulation = Shared._Prepare'。しかし、私はなぜあなたがしたいと思うのか全く分かりません。実際に何を達成しようとしていますか? –

+0

あなたは '_PrepareSimulation'と' _PrepareSimulator'を持っています - それは違うのですか? – tdelaney

+0

typo :)上位レベルのクラスはメソッドを上書きし、必要に応じてロジックをプラグインすることができます。ほとんどのクラスは基本クラスの機能を使用します – Paebbels

答えて

1

タイプセーフティを保証するデコレータベースのソリューションを作成することができました。最初のデコレータはローカルメソッドのエイリアスに注釈を付けます。エイリアスのターゲットを安全にする必要があります。 Aliasインスタンスを置き換え、エイリアスが型階層内のメソッドを指すかどうかを確認するには、2番目のデコレータが必要です。

デコレータ/別名の定義:

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 

使用例:@Alias(Shared2._Prepare)@Alias(Shared._Prepare)を設定

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() 

は、例外が発生します:

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

関連する問題