質問
私はPythonで値渡しの動作をエミュレートしたいと思います。言い換えれば、私は私が書く機能は、ユーザ供給されたデータを変更しないことを絶対に確認したいと思います。
1つの可能な方法は、深いコピーを使用することです。
from copy import deepcopy
def f(data):
data = deepcopy(data)
#do stuff
(など.clone()メソッドのように)渡されたオブジェクトについてできるだけ少数の仮定をし、この目標を達成するために存在し、より効率的な以上ののニシキヘビの方法です。
編集
私はPythonで技術的にすべてが値によって渡されることを承知しています。私はつまり、私は関数に渡されたデータと混乱していないことを確認すること、行動のエミュレートのに興味がありました。私は、最も一般的な方法は、独自のクローンのメカニズムまたはdeepcopyのいずれかで問題のオブジェクトのクローンを作成することであると思います。
解決
これを行うことのない神託の方法はありません。
Pythonは、このようなプライベートまたは読み取り専用データとしての施行のもののために非常にいくつかの機能を提供します。この場合には、これは仕様の一部ですが、コードには適用されません「機能は、データを変更するべきではない」ことを意味します神託の哲学は、「我々は、すべての同意大人をしている」ということです。
<時間>あなたがデータのコピーを作成したい場合は、あなたが得ることができる最も近いあなたのソリューションです。しかしcopy.deepcopy
は、非効率的であることに加えて、また警告を持っているなどのよう:
あなたは組み込みのPythonの種類や独自のオブジェクト(あなたがディープコピーのコピーのすべてのものなのでそれもコピー間で共有する必要がありすぎて、例えば、管理データ構造をコピーすることがあります。
[...]
このモジュールは、モジュール、メソッド、スタックトレース、スタックフレーム、ファイル、ソケット、ウィンドウ、アレイ、その他これらに類似の型のようなタイプをコピーしません。
__copy__
/ __deepcopy__
特別なメソッドを定義することにより、コピー動作をカスタマイズすることができる場所、なしがありますを扱っていることがわかっている場合は、だから私はそれをお勧めします)あなた自身のclone()
メソッドを定義する必要があります。
他のヒント
あなたはデコレータを作り、その中にクローニング行動を置くことができます。
>>> def passbyval(func):
def new(*args):
cargs = [deepcopy(arg) for arg in args]
return func(*cargs)
return new
>>> @passbyval
def myfunc(a):
print a
>>> myfunc(20)
20
これは最も堅牢な方法ではありません、そして、キーと値の引数やクラスメソッド(self引数の欠如)を処理しませんが、画像を取得します。
次の文が同じであることに注意してください:
@somedecorator
def func1(): pass
# ... same as ...
def func2(): pass
func2 = somedecorator(func2)
あなたも、デコレータは、クローニングを行い、これクローニング戦略を決定するデコレータのユーザーを許可する機能のいくつかの種類を取る可能性があります。その場合、デコレータは、おそらく最高__call__
オーバーライドさを持つクラスとして実装されます。
例えば、list
などの参照、として機能組み込みtypsの唯一のカップルがあります。
だから、私にとってこの例では、リストのために、値渡しを行うためのニシキヘビの方法で、次のようになります。
list1 = [0,1,2,3,4]
list2 = list1[:]
list1[:]
リスト1の新しいインスタンスを作成し、新しい変数に割り当てることができます。
たぶん、あなたはその型をチェックし、一つの引数を受け取ることができる機能を書き、そのresultaに従って、渡される引数の新しいインスタンスを返すことができ組み込み操作を行うことができます。
私が先に言ったように、、わずか数ビルトインタイプは、彼らの行動は、この例で参照、リストのようであること、がある。
任意の方法...それが役に立てば幸います。
通常、あなたは、例えばタプルにデータをラップし、不変オブジェクトとしてそれを渡すことによって、データの整合性を確保することができます。それはあなたのコードで予防しようとしたものであればこれは、変更することはできません。
私は他ののニシキヘビのオプションを把握することはできません。しかし、個人的に私はより多くののOO の方法を好むだろう。
class TheData(object):
def clone(self): """return the cloned"""
def f(data):
#do stuff
def caller():
d = TheData()
f(d.clone())
、私は期待しpickle
モジュールは、あなたが値として処理するすべてのビジネスを持っているすべてのコピーを提供します。
import pickle
def f(data):
data = pickle.loads(pickle.dumps((data)))
#do stuff
このさらにのuser695800のの答えを、との可能なリストの値渡し
def listCopy(l):
l[1] = 5
for i in l:
print i
タグと呼ばれます
In [12]: list1 = [1,2,3,4]
In [13]: listCopy(list1[:])
1
5
3
4
list1
Out[14]: [1, 2, 3, 4]