12

インターフェイスをリストに追加する Python クラスの関数があります。

def RegisterAsListener(self, inListener):
    self.__TransitListeners.append(inListener)

クラスは前述のインターフェイスから継承し、このオブジェクトを取得し、すべての更新のためにそれ自体を登録するだけでよいため、これは素晴らしいことです。

class ITransit():
    def TransitUpdate(self, data):
        raise NotImplementedError("You must define this function.")

(インターフェースを正しく作成したと仮定して)

このプロジェクトに参加しているのは私だけではないので、だれかが間違ったデータ型で RegisterAsListener 関数を呼び出してほしくありません。レジスター関数内に型をチェックするコードを入れることもできますが、プログラマーが間違ったデータ型を押し込もうとしたときに、コンパイラーがプログラマーに大声で怒鳴った方がずっと簡単です。

def RegisterAsListener(self, IListener inListener):
    self.__TransitListeners.append(inListener)

これを行う方法はありますか?

4

2 に答える 2

8

これを行わず、抽象基本クラス ( http://docs.python.org/2/library/abc.html )を使用して特定のメソッドの実装のみを強制することを強くお勧めしますが、可能です。

そのようなことを行う方法の例を次に示します: http://www.artima.com/weblogs/viewpost.jsp?thread=101605

# mm.py
registry = {}                                                                   

class MultiMethod(object):                                                      
    def __init__(self, name):                                                   
        self.name = name                                                        
        self.typemap = {}                                                       
    def __call__(self, *args):                                                  
        types = tuple(arg.__class__ for arg in args) # a generator expression!  
        function = self.typemap.get(types)                                      
        if function is None:                                                    
            raise TypeError("no match")                                         
        return function(*args)                                                  
    def register(self, types, function):                                        
        if types in self.typemap:                                               
            raise TypeError("duplicate registration")                           
        self.typemap[types] = function                                          

def multimethod(*types):                                                        
    def register(function):                                                     
        function = getattr(function, "__lastreg__", function)                   
        name = function.__name__                                                
        mm = registry.get(name)                                                 
        if mm is None:                                                          
            mm = registry[name] = MultiMethod(name)                             
        mm.register(types, function)                                            
        mm.__lastreg__ = function                                               
        return mm                                                               
    return register                                                             

    if hasattr(function, "__lastreg__"):                                        
        function = function.__lastreg__

そしてそれを使用するコード:

import mm                                                                       

@mm.multimethod(int)                                                            
def spam(a):                                                                    
    print 'Calling the int method'                                              
    print '%s: %r' % (type(a), a)                                               

@mm.multimethod(float)                                                          
def spam(a):                                                                    
    print 'Calling the float method'                                            
    print '%s: %r' % (type(a), a)                                               

spam(5)                                                                         
spam(5.0)

出力例:

Calling the int method
<type 'int'>: 5
Calling the float method
<type 'float'>: 5.0
于 2013-02-13T16:42:17.920 に答える
7

このプロジェクトに参加しているのは私だけではないので、だれかが間違ったデータ型で RegisterAsListener 関数を呼び出してほしくない

関数を徹底的に文書化してから、不適切なパラメーターが例外をスローするようにします。のユーザーはRegisterAListener、ドキュメントを使用して、関数が期待するデータの種類を知ることができる必要があります。また、誤ったパラメーターが指定された場合、結果の例外により、 のユーザーが何をRegisterAListener間違えたかが明確になるはずです。

于 2013-02-13T16:34:54.740 に答える