2017-08-28 19 views
1

部分的な関数自体を再定義することなく、Pythonの部分引数をリセットする方法はありますか?python:部分関数の引数をリセット

例えば、私は下にアキュムレータをリセットできるようにしたい:予想通り[5, 7]を印刷

accum = [] 
def accumulator(list, item): 
    list.append(item) 

a = partial(accumulator, accum) 
a(5) 
a(7) 
accum 

を。今、私は空にし、リストをリセットしたいのですが、a上で定義された動作を維持する:

accum = [] 
a(8) 
accum 

私は[8]を期待するが、この時、私の代わりに空のリストを取得します。定義された関数と外部スコープの変数との間の接続を維持する方法はありますか?

+1

:あなたは後にしている私は考えて何を達成するための一つの方法はクロージャを使用することです。 'a.args'でargsを見ることができますが、これはreadonly属性です。注意:引数 'list'を呼び出さないでください。ピリオド組み込みの' list'型を隠します。 – AChampion

答えて

6

partialは変数ではなくオブジェクトをバインドします。 aにはaccumが参照されているリストオブジェクトへの参照があり、accum変数への参照ではありません。 accumに割り当てると、partialオブジェクト内の参照ではなく、accum参照のみが再バインドされます。

あなたがリストオブジェクトクリアすることができますが:

accum.clear() 

やPython 3.3の前に:

del accum[:] 

partialが結合した可変オブジェクトとこの全体のセットアップは奇妙なエイリアシングおよびステートフルのレシピのように思えますバグ。あなたが解決しようとしている根本的な問題には、別のアプローチをお勧めします。

+0

実際には、関数を記述したくないが、状態(OOP)の関数が必要な場合があります。まだそれは推奨されない読み込みができませんメンテナンス可能かもしれないユーザーなど驚きかもしれません – Eytan

1

Pythonはclosureを作成しています。つまり、partialは関数aを返します。リストにポインタaccumが入っていれば、メモリに0x1と言うことができます。

0x2に新しいリストを作成し、変数accumのポインタを置き換えます。関数はまだ0x1を見ています。

あなたの希望の行動を与える

accum.clear() 

を使用することができます。

+0

これは閉鎖ではありません。閉包は実際には 'accum'を再割り当てすることによって影響されます*。 – user2357112

+0

@ user2357112あなたは間違っている(あるいは、あなたがどこにいたのかが異なると教えるかもしれない)。クロージャは、関数の実行に必要な環境を維持します。この場合、それはユーザコードの範囲外になるが、関数ではないリストオブジェクトです。あなたは、クロージャが保持していないオブジェクトをリストするポインタを指しています。 – Eytan

+0

クローズはオブジェクトではなく変数を覚えています。[クロージャで表示される方法は次のとおりです。](https://ideone.com/lBYiN4) – user2357112

0

他の人が触れたように、アプローチはおそらく良い考えではありません。私はオフに承知していることはありません

def accumulator(): 
    acc = [] #each time you call accumulator, you have a new list 
    def inner(item): 
     acc.append(item) #that list is shared on each call of the returned inner 
     return acc 
    return inner 

foo = accumulator() 

print(foo(2)) 
print(foo(3)) 
print(foo(4)) 

bar = accumulator() 
print(bar(9)) 
+0

を(computer_programming)アキュムレータ 'と呼ばれる。 – user2357112

+0

おっと - 愚かな間違いです。それを掃除するための編集。 – Solaxun

+0

あなたのコードは今動作しますが、質問は "部分的な関数自体を再定義する必要なし"と言っていました。私は新しいバーの創造がそれに反すると思う。 – user2357112

関連する問題