14

Pythonでこれが奇妙であることがわかりました:

class SomeClass():
    def __init__(self):
        pass

a = [SomeClass()]
b = copy.deepcopy(a)

出力:

>>> a
[<__main__.Some instance at 0x10051b1b8>]
>>> b
[<__main__.Some instance at 0x10051b092>]

これは予想どおりです。deepcopy によってSomeClass()b の新しいオブジェクトが作成されました。

しかし、もし、

f = lambda x:x+1
a = [f]
b = copy.deepcopy(a)

私は得る:

>>> a
[<function <lambda> at 0x10056e410>]
>>> b
[<function <lambda> at 0x10056e410>]

2 番目のケースでディープコピーが新しいラムダ インスタンスを作成しないのはなぜですか? それはラムダ関数がアトミックであることを意味しますか?

4

4 に答える 4

6

これはラムダだけでなく、より一般的に状態のない関数にも当てはまります。

>>> def some_function(word): print word
>>> a = [some_function]
>>> a
[<function some_function at 0x1007026e0>]
>>> copy.deepcopy(a)
[<function some_function at 0x1007026e0>]

関数は状態を保存しないため、deepcopy はそれらの新しい参照を作成しません。この問題 (まったく同じ問題ではありませんが) に類似したトピックに関する興味深い議論がここに記録されています: http://bugs.python.org/issue1515

于 2012-05-29T15:30:01.270 に答える
5

ラムダは変更可能ではないと考えている一部の人々への補足として、次の動作を観察してください。

>>> a = lambda x: x + 1
>>> a(12)
13
>>> b = lambda x: x - 1
>>> b(12)
11
>>> a.__code__ = b.__code__
>>> a(12)
11
>>> 
于 2012-05-29T16:20:55.637 に答える
4

ソースコードの 222 行目と 223行目を見てください。

d[types.BuiltinFunctionType] = _deepcopy_atomic
d[types.FunctionType] = _deepcopy_atomic

モジュールはそれらをアトミックと見なしますが、ラムダを変更する方法がわかりません。

于 2012-05-29T15:22:52.187 に答える
0

私は Python の完全な歴史を知りませんが、関数が文字列やタプルと同じように不変であった可能性deepcopyはあります。

また、実際には、ほとんどの人は、関数よりもデータ オブジェクトがコピーされることに関心があります。関数のコピーを作成する必要性deepcopyは明確なエッジ ケースであり、そのエッジ ケースの対象となる人々が独自のソリューションを作成することを期待することは、私にはまったく問題ないように思えます。

@copyablefunc合理的なアプローチは、呼び出し可能なオブジェクト (つまり、メソッドを持つクラス) で関数をラップし、ルーチンで使用されるメソッドを定義__call__()するデコレーターを作成することです。__copy__()__deepcopy__()deepcopy

copy.deepcopyちなみに、クラスを真にコピーするわけでもありません。

于 2012-05-29T17:40:15.347 に答える