Python에서 사전을 복사하는 빠른 방법


92

사전과 많이 작동하는 Python 프로그램이 있습니다. 사전을 수천 번 복사해야합니다. 키와 관련 내용의 사본이 필요합니다. 사본은 편집되며 원본에 연결되어서는 안됩니다 (예 : 사본의 변경 사항이 원본에 영향을주지 않아야 함).

키는 문자열이고 값은 정수 (0/1)입니다.

현재 간단한 방법을 사용합니다.

newDict = oldDict.copy()

내 코드를 프로파일 링하면 복사 작업에 대부분의 시간이 걸린다는 것을 알 수 있습니다.

dict.copy()방법 에 대한 더 빠른 대안이 있습니까? 가장 빠른 것은 무엇입니까?


1
값이 0 또는 1 일 수있는 bool경우는 int?
Samir Talwar

5
수천 개의 사본이 필요한 경우 비트 마스크가 더 잘 작동할까요?
Wooble 2011 년

@Samir는 어쨌든 bool파이썬에 없습니다 int.
Santa

하지만 비트 마스크가 더 효율적일 수 있다는 데 동의합니다 (이 "dict"를 실제로 사용하는 방법에 따라 다름).
Santa

1
명확히하기 위해 bool유형은 실제로 유형의 하위 클래스 (하위 유형?)입니다 int.
Santa

답변:


64

Python 작업 의 C 소스 를 살펴보면 dict매우 순진하지만 효율적인 복사를 수행하는 것을 알 수 있습니다. 본질적으로 다음과 같은 호출로 요약됩니다 PyDict_Merge.

PyDict_Merge(PyObject *a, PyObject *b, int override)

이것은 그들이 같은 객체인지, 객체가 있는지와 같은 것들을 빠르게 확인합니다. 그 후 대상 dict에 한 번 크기 조정 / 할당을 한 다음 요소를 하나씩 복사합니다. 나는 당신이 내장 된 copy().


1
딕셔너리를 전혀 사용하지 않기 위해 코드를 다시 작성하거나 동일한 작업을 수행 할 수있는 더 빠른 데이터 구조를 사용하는 것이 좋습니다. 답변 해 주셔서 대단히 감사합니다!
Joern

56

당신이 말했듯이 dict.copy가 더 빠릅니다.

[utdmr@utdmr-arch ~]$ python -m timeit -s "d={1:1, 2:2, 3:3}" "new = d.copy()"
1000000 loops, best of 3: 0.238 usec per loop
[utdmr@utdmr-arch ~]$ python -m timeit -s "d={1:1, 2:2, 3:3}" "new = dict(d)"
1000000 loops, best of 3: 0.621 usec per loop
[utdmr@utdmr-arch ~]$ python -m timeit -s "from copy import copy; d={1:1, 2:2, 3:3}" "new = copy(d)"
1000000 loops, best of 3: 1.58 usec per loop

비교해 주셔서 감사합니다! 대부분의 장소에서 dict 복사를 사용하지 않도록 코드를 다시 작성하려고합니다. 다시 한 번 감사드립니다!
Joern

4
매번 가져 오기를 수행하는 비용을 계산하지 않고 마지막 비교를 수행하는 방법은 timeit-s인수를 사용하는 것입니다 : python -m timeit -s "from copy import copy" "new = copy({1:1, 2:2, 3:3})". 그 동안 딕셔너리 생성도 꺼냅니다 (모든 예).
Thomas Wouters

특정 샷에 약간의 변동이있을 수 있으므로 프로세스를 여러 번 반복하는 것이 더 좋습니다.
xiaohan2012

2
Timeit는 그렇게합니다. 그것은 1000000 번 반복하고 평균을 낸다고 말합니다.
utdemir 2014

타이밍이 맞지 않습니다. a = {b : b for b in range (10000)} In [5] : % timeit copy (a) 10000 루프, 루프 당 최고 3 : 186 µs In [6] : % timeit deepcopy (a) 100 루프, 최고 3 : 루프 당 14.1 ms In [7] : % timeit a.copy () 1000 루프, 최고 3 : 루프 당 180 µs
Davoud Taghawi-Nejad 2015

12

copy ()를 사용하는 방법과 어떤 컨텍스트에서 사용하는지 확인할 수 있도록 코드 샘플을 제공 할 수 있습니까?

당신은 사용할 수 있습니다

new = dict(old)

그러나 나는 그것이 더 빠를 것이라고 생각하지 않습니다.


5

나는 이것이 오래된 스레드라는 것을 알고 있지만 이것은 "dict copy python"에 대한 검색 엔진에서 높은 결과이고 "dict copy performance"에 대한 상위 결과이며 이것이 관련이 있다고 생각합니다.

Python 3.7부터는 newDict = oldDict.copy()이전보다 최대 5.5 배 빠릅니다. 특히 지금 newDict = dict(oldDict)은 이러한 성능 향상이없는 것 같습니다.

여기에 조금 더 많은 정보가 있습니다 .


3

추측에 맡기는 것에 따라 원본 사전을 래핑하고 일종의 copy-on-write를 원할 수 있습니다 .

"복사본"은 "부모"사전에있는 내용을 검색하는 사전입니다. 만약 이미 키를 포함하고 있지 않다면 --- 그 자체로 수정 사항을 담습니다.

이것은 원본을 수정하지 않을 것이며 추가 조회로 인해 더 많은 비용이 들지 않는다고 가정합니다.


2

측정은 사전 크기에 따라 다릅니다. 10000 항목의 경우 copy (d) 및 d.copy ()는 거의 동일합니다.

a = {b: b for b in range(10000)} 
In [5]: %timeit copy(a)
10000 loops, best of 3: 186 µs per loop
In [6]: %timeit deepcopy(a)
100 loops, best of 3: 14.1 ms per loop
In [7]: %timeit a.copy()
1000 loops, best of 3: 180 µs per loop
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.