2017-08-11 12 views
0

次のコードだ場合、動的に適応:エラー以下は、コールバックを使用して、インスタンス機能や簡単な関数

def foo(a): 
    print(a) 

class Bar(object): 
    def foo(self, a): 
     print(a) 
bar = Bar() 


class A(object): 
    callback1 = foo 
    callback2 = bar.foo 

    def do(self): 
     self.callback2(1) 
     self.callback1(1) 


A().do() 

プロデュース:

Traceback (most recent call last): 
    File "/home/bastien/Projects/test/t.py", line 19, in <module> 
    A().do() 
    File "/home/bastien/Projects/test/t.py", line 16, in do 
    self.callback1(1) 
TypeError: foo() takes 1 positional argument but 2 were given 

機能fooので、インスタンスの関数のように使用されています。 foo関数に@staticmethodデコレータを追加することはできますが、A.doの実行前に単純な関数としてコールバックを使用することは可能です(A.doの実行前にはわからないと考えてください)?

答えて

0

を:

# -*- coding: utf-8 -*- 
import types 


def foo(a): 
    print(a) 

class Bar(object): 
    def foo(self, a): 
     print(a) 
bar = Bar() 


def prepare_callback(callback): 
    if isinstance(callback, types.FunctionType): 
     return lambda self, *args, **kwargs: callback(*args, **kwargs) 
    return callback 


class A(object): 
    callback1 = prepare_callback(foo) 
    callback2 = prepare_callback(bar.foo) 

    def do(self): 
     self.callback2(1) 
     self.callback1(1) 


A().do() 

しかし、よりスマートな方法は、クラス属性を使用しないことです。

# -*- coding: utf-8 -*- 

def foo(a): 
    print(a) 

class Bar(object): 
    def foo(self, a): 
     print(a) 
bar = Bar() 


class A(object): 
    def __init__(self, callback1, callback2): 
     self.callback1 = callback1 
     self.callback2 = callback2 

    def do(self): 
     self.callback1(1) 
     self.callback2(1) 


A(foo, bar.foo).do() 
1

最初のfoo関数をドット参照で呼び出すと、それをインスタンスメソッドに変換します。このメソッドは通常、最初の引数としてインスタンスを渡します。渡された引数の数が2になり、fooのシグネチャが一致しなくなります。

この機能-方式変換の効果をボイコットするには、__func__を使用して、元の関数オブジェクトを呼び出すことができます。

class A(object): 
    callback1 = foo 
    callback2 = bar.foo 

    def do(self): 
     self.callback2(1) 
     self.callback1.__func__(1) 

bar.fooがバインドされた方法である一方でfooは、バニラ関数であることに注意してください。

+0

「A.doの実行前に私たちが知ることはできないと考えてください」 – bux

+0

@bux AreあなたはPython 2または3で? –

+0

私はPython 3を使用しています。 – bux

-1

あなたは以下のコードを使用できます。コールバックの種類が正しくコールバックを調製するために使用することができます

callback = foo.__func__ if "__func__" in foo.__dir__() else foo 
関連する問題