Python の copy と deepcopy の違い



copyちょっとだけコピー
deepcopy全部コピー





f:id:domodomodomo:20171106122644j:plain




何を言っているのか、全くわかりません。そこでスライドを作りました。まず identity とは何かについて、簡単にイメージ説明して、そのあと copy と deepcopy の違いを説明しています。


実際に触って動作を確認してみる。

オブジェクトが持っている identity を全て表示する ids という関数を作って、実際にどのようにコピーされているかを確認して見ました。identity がどのように変化するでしょうか。

def sample_code():

    pc = Computer(
        Cpu('2.3GHz', 5),
        Memory('8GB', '2133MHz', 'DDR4'),
        Ssd('256GB'))

    print('# pc')
    pprint.pprint(ids(pc))

    print('# copy.copy(pc)')
    print('#   copy.copy creates only one instance\n'
          '#   contained in variable.')
    pprint.pprint(ids(copy.copy(pc)))

    print('# copy.deepcopy(pc)')
    print('#   copy.deepcopy creates all intances\n'
          '#   contained in variables and attributes except immutable objects')
    pprint.pprint(ids(copy.deepcopy(pc)))
$ python ids.py 
# pc
(4510800024,
 {'auxiliary_memory': (4510185176, {'volume': 4510149464}),
  'cpu': (4510150328, {'clock': 4509278648, 'core': 4507450848}),
  'primary_memory': (4510150384,
                     {'clock': 4510076408,
                      'type_': 4510076464,
                      'volume': 4510076352})})
# copy.copy(pc)
#   copy.copy creates only one instance
#   contained in variable.
(4510800080,
 {'auxiliary_memory': (4510185176, {'volume': 4510149464}),
  'cpu': (4510150328, {'clock': 4509278648, 'core': 4507450848}),
  'primary_memory': (4510150384,
                     {'clock': 4510076408,
                      'type_': 4510076464,
                      'volume': 4510076352})})
# copy.deepcopy(pc)
#   copy.deepcopy creates all intances
#   contained in variables and attributes except immutable objects
(4510800080,
 {'auxiliary_memory': (4511027720, {'volume': 4510149464}),
  'cpu': (4510820392, {'clock': 4509278648, 'core': 4507450848}),
  'primary_memory': (4510872856,
                     {'clock': 4510076408,
                      'type_': 4510076464,
                      'volume': 4510076352})})
$


copy, deepcopy 関数は、str や int などの immutable なオブジェクトは、singleton として取り扱い、コピーしません。

def _copy_immutable(x):
    return x


list, dict, set には専用の copy メソッドがあります。もし copy(list(range(3))) とlist(range(3)).copy() の違いってなんだろうと思われるかもしれませんが、同じことをしています。copy(list(range(3))) は、単純に list.copy メソッドを呼び出しているだけです。

d[list] = list.copy
d[dict] = dict.copy
d[set] = set.copy
d[bytearray] = bytearray.copy