2017-01-24 8 views
-2

私たちは、関数はオブジェクトでもあることを知っています。しかし、関数オブジェクトはどのように関数と比較されますか?関数オブジェクトと関数の違いは何ですか?関数オブジェクトによってPythonの "関数オブジェクト"は機能していますか?

私はそのように定義されグラムを意味:

class G(object): 
    def __call__(self, a): 
     pass 
g = G() 

機能では、私はこの意味:

def f(a): 
    pass 
+7

"プレーン関数"とはなんですか? –

+3

あなたの意見に関数オブジェクトと関数が何であるかの例を挙げてください。 –

+1

これは、Pythonでの*単純な 'int' *と' int'オブジェクト*の違いは何ですか?これは単純な 'int's *ではありません。 –

答えて

2

あなたはDEFステートメントを使用するときPythonはあなたのための関数オブジェクトを作成し、または使用をラムダ式:

>>> def foo(): pass 
... 
>>> foo 
<function foo at 0x106aafd70> 
>>> lambda: None 
<function <lambda> at 0x106d90668> 

したがって、Pythonで関数を定義するときはいつでも、このようなオブジェクトが作成されます。 はありません。の機能定義方法はありません。

+1

OPが彼の質問を明確にした後、これは無関係のようです。 –

+0

'function'オブジェクトには属性 '__set__'がありますか?属性 '__get__'はどうですか?あなたは私の質問に答えていません。 – jimifiki

1

TLは、DR__call__は例えば呼び出すことができます実装する任意のオブジェクト:機能、カスタムクラス、など。

少し長いバージョン:(すべて O Fトン内線ワット)

python仮想マシンの実装内に何があるのか​​という相違点についての完全な答えがあるので、私たちはそのフードの下でPythonを見ていかなければなりません。まず、コードオブジェクトの概念があります。 Pythonは、あなたがそれに投げるものをパースします。それは、バイトコードとして知られるすべてのプラットフォームで同じ内部言語です。これを視覚的に再現するのは、作成したカスタムライブラリをインポートした後に.pycファイルを取得する場合です。これらは、Python VMの生の指示です。これらの命令がソースコードからどのように作成されるのかを無視して、PyEval_EvalFrameExPython/ceval.cで実行します。ソースコードは獣のビットですが、最終的には複雑なビットを抽象化した単純なプロセッサのように機能します。バイトコードは、このプロセッサのアセンブリ言語です。特に、この「プロセッサ」の「オペコード」の1つは、CALL_FUNCTIONです。コールバックは、最終的にPyObject_Call()に到達するいくつかの呼び出しを経由します。この関数は、PyObjectへのポインタを取り、それのタイプからtp_call属性を抽出し、それを直接呼び出す(それが最初だ場合、技術的に、それはチェック):__call__を実装する任意のオブジェクトがポインタでtp_call属性が付与され

... 
call = func->ob_type->tp_call //func is an arg of PyObject_Call() and is a pointer to a PyObject 
... 
result = (*call)(func, arg, kw); 

実際の関数に渡します。 CPythonの実装で定義され、それはPythonのVMがのためにバイトコードの実行を開始すべき方法を定義している機能のため

FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call, 
     "__call__($self, /, *args, **kwargs)\n--\n\nCall self as a function.", 
     PyWrapperFlag_KEYWORDS) 

__call__方法自体:私はそれをオブジェクト/ typeobject.cからslotdefs[] difinitionによって処理されると信じその関数とデータが返される方法(存在する場合)任意のクラスに__call__メソッドを渡すと、その属性は関数オブジェクトであり、再び__call__のcpython実装を参照します。したがって、「通常の」関数を呼び出すときは、foo.__call__が参照されます。呼び出し可能なクラスを呼び出すと、self.__call__fooに相当し、呼び出される実際のcpython参照はself.__call__.im_func.__call__です。

免責事項

これは私のために多少未知の水域への旅であったが、それは私が実装の細かい点の一部を誤って伝えてきたことは完全に可能です。私は主にthisからpython callablesがどのように動作しているか、そしてpythonを通して私自身のものを掘り下げたブログ記事を取得しました。

+0

お返事ありがとうございました。実際には、なぜ、 'function'オブジェクトに属性 '__set__'と '__get__'がないのかといった、高水準言語の機能についてもっと疑問に思っていました。しかし、あなたの答えにあなたが提供した情報も面白いと感じました。 – jimifiki

+0

関数は '__get__'を実装します。これは、" " – Aaron

+0

というテキストを返すものです。gettersとsetterを使用して、クラス自体ではなくクラスの個々のプロパティに適用する方がはるかに一般的です。また、基本的なオブジェクトクラスから継承しない関数もあります。カスタムビヘイビアが必要な場合は、クラスで実装することができます。技術的には独自の関数クラスを作成することはできますが、それは非常に遅く複雑になります。ベースオブジェクトクラスから継承しないことで、Pythonはコードオブジェクトの呼び出しを管理する代わりにCコードを実行できます – Aaron

関連する問題