2016-05-05 10 views
2

私は3つの間で混乱しています。 adderが閉鎖され、ここでクローズ、パーシャル、デコレータ

def add_nums(one): 
    def adder(two): 
     return one+two 
    return adder 

a_10 = add_nums(10) 
print a_10(5) 
15 

:私は囲みスコープを形成

例のクロージャは、別の関数によって返さ関数であり、ローカル変数へのアクセスを持っていることを理解しています。

しかし、これは二つの違いは何ですか?またpartial

from functools import partial 
a_10 = partial(add_nums, 10) 
print a_10()(5) 
15 

の例ではありませんか

また、デコレータは機能に機能を追加するために使用されます。

3つの違いは何ですか?

+0

デコレータは、関数を受け取り関数を返す単なる関数です。これはしばしばネストされた関数を含んでいるので、内部関数が環境をキャプチャするクロージャを介して引数関数にアクセスするのが一般的ですが、値を明示的に渡す部分的な方法で実装することができます。あなたが知りたいと思うものは明らかではありません。 – jonrsharpe

答えて

-1

あなたのデコレータの部分的なバージョンは、実際に次のようになります。

def add_nums(one): 
    def adder(one, two): 
     return one + two 
    return partial(adder, one) 

注ネストされた関数ということになりましたのみない閉鎖、明示的なパラメータを使用しています。クロージャ、partial(これはimplemented using a closure)またはその2つの組み合わせを使用して、関数を受け取り、(通常は異なる)関数を返す関数であるデコレータを実装できます。

+0

あなたはクロージャーを事物と呼んでいます。あなたの言葉ではっきりと閉鎖は何ですか? –

+0

クロージャは、関数が呼び出されたときに、関数が作成された場所に基づいて利用できる環境です。クロージャーのバージョンでは、内部関数は明示的なパラメータまたはグローバル変数としてではなく、暗黙的に 'one 'にアクセスできます。なぜなら、関数が作成された場所で利用可能だったからです。 – jonrsharpe

2

短い回答:閉鎖がメカニズムですが、functools.partialとデコレータはそのメカニズムの典型的な使用です。

クロージャとより典型的な名前空間の主な違いは、コントロールフローが最上位レベルの機能を去ったときに、「クローズオーバー」名前空間の名前と値が消えないことです。それらは、内部関数の1つのインスタンスに関連付けられたミニ名前空間に保持され、そのインスタンスが行う限り存続します。

functools.partialは、既存の機能に対するいくつかの引数を「記憶」する能力を使用します。デコレータは、通常、同じ理由でその能力を使用します。

デコレータはそれ以上の柔軟性があることに注意してください。 1つのパラメータをとり、何かを返すコール可能なものはすべてデコレータとして機能します。 にはがないので、Pythonクロージャを使用したり、関数を返すことさえできません。多くのデコレータは、代わりに呼び出し可能なオブジェクトを返します。 (別名として、名前空間のオブジェクトと内部関数のメソッドを使用して、クロージャーと内部関数をシミュレートすることができます)

デコレータが返すものはすべて、名前に割り当てられます。でした。 (@decorator('args') ...のような彼らの後に括弧付きデコレータは、もう少し複雑である。)一般的なデコレータ構文:

@decorator 
def function(): 
    pass 

...「飾ると再割り当て、その後、定義」のためだけの省略形です:

def function(): 
    pass 
function = decorator(function) 

極端な(とほとんど役に立たない)例:

def decorator5(__): 
    return 5 

@decorator5 
def square(x): 
    return x * x 

print(square) # Prints 5 --- the function is gone. 
square(10)  # TypeError: 'int' object is not callable 
3

私はあなたが実装で目的を混乱していると思います。クロージャを作成することは、何かをするためのテクニックです。あなたはクロージャーでたくさんのことをすることができます。

他方、partialおよびdecoratorは、特定の目的である。たぶん彼らはクロージャーを使うでしょう。多分彼らはしません。これは実装の詳細なので、心配する必要はありません。重要なことは、あなたが望む結果を達成することです。

partialと考えてください。それはクロージャを使用することです作成する1つの方法(** kwargsからは無視):

def partial(f, *args): 
    def pf(*rest): 
     return f(*args, *rest) 
    return pf 

をしかし、それはそのようにする必要はありません。例:

class Partial: 
    def __init__(self, func, args): 
     self.args = args 
     self.func = func 

    def __call__(self, *rest): 
     f = self.func 
     args = self.args 
     return f(*args, *rest) 

def partial(f, *args): 
    return Partial(f, args) 

ここでは、他の変数への参照を保持する変数はありません。しかし、私は部分的な行動を取るので、誰が気にしますか?

デコレータも同様です。デコレータはクロージャでも、そうでないかもしれません。たとえば、最近の質問の1つは、関数の__doc__文字列でstr.formatを実行することでした。これは、関数オブジェクトを受け入れ、__doc__属性を変更し、同じオブジェクトを返す場合に過ぎません。明らかに、そこに閉鎖はありません。