Cela dépend vraiment de vos besoins. deepcopy
a été construit avec l'intention de faire la chose (la plus) correcte. Il garde les références partagées, il ne récure pas dans des structures récursives infinies et ainsi de suite... Il peut le faire en gardant une memo
dictionnaire dans lequel toutes les "choses" rencontrées sont insérées par référence. C'est ce qui le rend assez lent pour les copies de données pures. Cependant, je voudrais presque disent toujours que deepcopy
es la façon la plus pythique de copier des données même si d'autres approches pourraient être plus rapides.
Si vous disposez de données pures et d'un nombre limité de types, vous pouvez créer votre propre système de gestion des données. deepcopy
(construire à peu près après la mise en œuvre de deepcopy
dans CPython ) :
_dispatcher = {}
def _copy_list(l, dispatch):
ret = l.copy()
for idx, item in enumerate(ret):
cp = dispatch.get(type(item))
if cp is not None:
ret[idx] = cp(item, dispatch)
return ret
def _copy_dict(d, dispatch):
ret = d.copy()
for key, value in ret.items():
cp = dispatch.get(type(value))
if cp is not None:
ret[key] = cp(value, dispatch)
return ret
_dispatcher[list] = _copy_list
_dispatcher[dict] = _copy_dict
def deepcopy(sth):
cp = _dispatcher.get(type(sth))
if cp is None:
return sth
else:
return cp(sth, _dispatcher)
Cela ne fonctionne correctement que pour tous les types immuables non-conteneur et list
y dict
instances. Vous pouvez ajouter d'autres répartiteurs si vous en avez besoin.
# Timings done on Python 3.5.3 - Windows - on a really slow laptop :-/
import copy
import msgpack
import json
import string
data = {'name':'John Doe','ranks':{'sports':13,'edu':34,'arts':45},'grade':5}
%timeit deepcopy(data)
# 11.9 µs ± 280 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit copy.deepcopy(data)
# 64.3 µs ± 1.15 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit json.loads(json.dumps(data))
# 65.9 µs ± 2.53 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit msgpack.unpackb(msgpack.packb(data))
# 56.5 µs ± 2.53 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Voyons également comment il se comporte lors de la copie d'un grand dictionnaire contenant des chaînes de caractères et des entiers :
data = {''.join([a,b,c]): 1 for a in string.ascii_letters for b in string.ascii_letters for c in string.ascii_letters}
%timeit deepcopy(data)
# 194 ms ± 5.37 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit copy.deepcopy(data)
# 1.02 s ± 46.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit json.loads(json.dumps(data))
# 398 ms ± 20.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit msgpack.unpackb(msgpack.packb(data))
# 238 ms ± 8.81 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)