[python] 짧은 파이썬 목록을 추가하기위한 관용구 문은 무엇입니까?

list.append()목록 끝에 추가하기위한 확실한 선택입니다. 다음 은 실종에 대한 합리적인 설명 입니다 list.prepend(). 내 목록이 짧고 성능 문제가 무시할 만하다고 가정하면

list.insert(0, x)

또는

list[0:0] = [x]

관용?



답변

s.insert(0, x)형태가 가장 일반적이다.

그래도 볼 때마다 목록 대신 collections.deque 를 사용하는 것이 좋습니다.


답변

기능적인 방법으로 갈 수 있다면 다음이 분명합니다.

new_list = [x] + your_list

물론 당신은 삽입하지 않은 x으로 your_list오히려 당신과 함께 새 목록 생성 한, x그것에 preprended을.


답변

짧은 파이썬 목록을 추가하기위한 관용구 문은 무엇입니까?

일반적으로 Python의 목록 앞에 반복적으로 추가하고 싶지 않습니다.

그것의 경우 짧은 , 당신이 그것을 많이 안하고 … 다음 확인을 클릭합니다.

list.insert

list.insert이 방법을 사용할 수 있습니다.

list.insert(0, x)

그러나 파이썬에서는 a list가 포인터의 배열이므로 파이썬은 목록의 모든 포인터를 가져 와서 포인터를 첫 번째 슬롯에 객체에 삽입하기 위해 하나씩 아래로 이동해야하므로 비효율적입니다. 당신이 요청 한대로 오히려 짧은 목록.

CPython 소스 의 스 니펫 다음과 같습니다. 여기서 알 수 있듯이 배열의 끝에서 시작하여 모든 삽입마다 하나씩 아래로 이동합니다.

for (i = n; --i >= where; )
    items[i+1] = items[i];

요소 앞에 붙일 수있는 컨테이너 / 목록을 원한다면 연결된 목록이 필요합니다. 파이썬은 이중 연결리스트를 가지고 있는데, 처음에는 빠르게 삽입하고 끝낼 수 deque있습니다.

deque.appendleft

A collections.deque에는 목록의 많은 방법이 있습니다. list.sort만들기 예외 인 deque에 대한 결정적 전적으로 Liskov의 대용은 list.

>>> set(dir(list)) - set(dir(deque))
{'sort'}

deque또한 갖는다 appendleft방법 (뿐만 아니라 popleft). 는 deque이중 종료 큐와 이중 연결리스트이다 -에 상관없이 길이는 항상 preprend 뭔가에 동일한 시간이 소요됩니다. 큰 O 표기법에서 O (1) 대 목록의 O (n) 시간. 사용법은 다음과 같습니다.

>>> import collections
>>> d = collections.deque('1234')
>>> d
deque(['1', '2', '3', '4'])
>>> d.appendleft('0')
>>> d
deque(['0', '1', '2', '3', '4'])

deque.extendleft

또한 deque의 extendleft방법 이 관련이 있으며 반복적으로 앞에 붙습니다.

>>> from collections import deque
>>> d2 = deque('def')
>>> d2.extendleft('cba')
>>> d2
deque(['a', 'b', 'c', 'd', 'e', 'f'])

각 요소는 한 번에 하나씩 추가되므로 순서를 효과적으로 반대로 바꿉니다.

list대 성능deque

먼저 우리는 몇 가지 반복적 인 접두사로 설정합니다.

import timeit
from collections import deque

def list_insert_0():
    l = []
    for i in range(20):
        l.insert(0, i)

def list_slice_insert():
    l = []
    for i in range(20):
        l[:0] = [i]      # semantically same as list.insert(0, i)

def list_add():
    l = []
    for i in range(20):
        l = [i] + l      # caveat: new list each time

def deque_appendleft():
    d = deque()
    for i in range(20):
        d.appendleft(i)  # semantically same as list.insert(0, i)

def deque_extendleft():
    d = deque()
    d.extendleft(range(20)) # semantically same as deque_appendleft above

그리고 성능 :

>>> min(timeit.repeat(list_insert_0))
2.8267281929729506
>>> min(timeit.repeat(list_slice_insert))
2.5210217320127413
>>> min(timeit.repeat(list_add))
2.0641671380144544
>>> min(timeit.repeat(deque_appendleft))
1.5863927800091915
>>> min(timeit.repeat(deque_extendleft))
0.5352169770048931

deque가 훨씬 빠릅니다. 목록이 길어질수록 deque가 더 잘 수행 될 것으로 기대합니다. deque를 사용할 수 있다면 extendleft아마도 최고의 성능을 얻을 것입니다.


답변

누군가 나처럼이 질문을 찾으면 제안 된 방법에 대한 성능 테스트가 있습니다.

Python 2.7.8

In [1]: %timeit ([1]*1000000).insert(0, 0)
100 loops, best of 3: 4.62 ms per loop

In [2]: %timeit ([1]*1000000)[0:0] = [0]
100 loops, best of 3: 4.55 ms per loop

In [3]: %timeit [0] + [1]*1000000
100 loops, best of 3: 8.04 ms per loop

보시다시피 insert슬라이스 할당은 명시 적 추가보다 거의 두 배 빠르며 결과는 매우 가깝습니다. 로 레이몬드 Hettinger는 지적은 insert일반적인 옵션이며 나는 개인적으로 목록에 앞에 추가에이 방법을 선호합니다.


답변