append()
목록 방법 과 의 차이점은 무엇입니까 extend()
?
[python] Python의 목록 메서드 추가와 확장의 차이점은 무엇입니까?
append
목록 끝에 지정된 객체를 추가합니다.
>>> x = [1, 2, 3]
>>> x.append([4, 5])
>>> print(x)
[1, 2, 3, [4, 5]]
extend
지정된 iterable에서 요소를 추가하여 목록을 확장합니다.
>>> x = [1, 2, 3]
>>> x.extend([4, 5])
>>> print(x)
[1, 2, 3, 4, 5]
append
목록에 요소를 추가합니다. extend
첫 번째 목록을 다른 목록/반복 가능 항목과 연결합니다.
>>> xs = ['A', 'B']
>>> xs
['A', 'B']
>>> xs.append("D")
>>> xs
['A', 'B', 'D']
>>> xs.append(["E", "F"])
>>> xs
['A', 'B', 'D', ['E', 'F']]
>>> xs.insert(2, "C")
>>> xs
['A', 'B', 'C', 'D', ['E', 'F']]
>>> xs.extend(["G", "H"])
>>> xs
['A', 'B', 'C', 'D', ['E', 'F'], 'G', 'H']
목록 메서드 추가와 확장의 차이점은 무엇입니까?
append
목록의 끝에 단일 요소로 인수를 추가합니다. 목록 자체의 길이가 1씩 늘어납니다.extend
인수를 반복하여 목록에 각 요소를 추가하여 목록을 확장합니다. 목록의 길이는 iterable 인수에 있는 요소의 수만큼 증가합니다.
append
이 list.append
메서드는 목록 끝에 개체를 추가합니다.
my_list.append(object)
개체가 무엇이든, 숫자, 문자열, 다른 목록 또는 다른 무엇이든 목록 my_list
의 단일 항목으로 끝에 추가됩니다.
>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
따라서 목록은 객체임을 명심하십시오. 목록에 다른 목록을 추가하는 경우 첫 번째 목록은 목록 끝에 있는 단일 개체가 됩니다(원하는 것이 아닐 수도 있음).
>>> another_list = [1, 2, 3]
>>> my_list.append(another_list)
>>> my_list
['foo', 'bar', 'baz', [1, 2, 3]]
#^^^^^^^^^--- single item at the end of the list.
extend
이 list.extend
메서드는 iterable에서 요소를 추가하여 목록을 확장합니다.
my_list.extend(iterable)
따라서 확장을 사용하면 iterable의 각 요소가 목록에 추가됩니다. 예를 들어:
>>> my_list
['foo', 'bar']
>>> another_list = [1, 2, 3]
>>> my_list.extend(another_list)
>>> my_list
['foo', 'bar', 1, 2, 3]
문자열은 반복 가능하므로 목록을 문자열로 확장하는 경우 문자열을 반복할 때 각 문자를 추가해야 합니다(원하는 것이 아닐 수 있음).
>>> my_list.extend('baz')
>>> my_list
['foo', 'bar', 1, 2, 3, 'b', 'a', 'z']
연산자 과부하, __add__
( +
) 및 __iadd__
( +=
)
+
및 +=
연산자는 모두 에 대해 정의됩니다 list
. 그들은 확장과 의미상 유사합니다.
my_list + another_list
메모리에 세 번째 목록을 생성하므로 결과를 반환할 수 있지만 두 번째 iterable은 목록이어야 합니다.
my_list += another_list
새 목록을 생성하지 않도록 목록을 제자리에서 수정합니다(내부 연산자이고 목록은 변경 가능한 객체입니다 ) . 또한 두 번째 iterable은 모든 종류의 iterable이 될 수 있다는 점에서 확장과 같이 작동합니다.
혼동하지 마십시오 - my_list = my_list + another_list
와 동일 하지 않음 +=
- my_list에 할당된 완전히 새로운 목록을 제공합니다.
시간 복잡도
추가는 ( 상각된 ) 일정한 시간 복잡도 , O(1)을 가집니다.
확장은 시간 복잡도 O(k)를 가집니다.
여러 호출을 반복 append
하여 복잡성을 추가하여 확장과 동일하게 만들고 확장의 반복이 C로 구현되기 때문에 반복 가능한 항목에서 목록에 연속적인 항목을 추가하려는 경우 항상 더 빠릅니다.
"상각"에 대해 - 목록 개체 구현 소스 에서 :
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
이것은 우리가 필요한 것보다 더 큰 메모리 재할당의 이점을 미리 얻을 수 있음을 의미하지만 더 큰 것으로 다음 한계 재할당에서 비용을 지불할 수 있습니다. 모든 추가에 대한 총 시간은 O(n)에서 선형이며 추가당 할당된 시간은 O(1)이 됩니다.
성능
추가를 사용하여 확장과 동일한 결과를 얻을 수 있으므로 무엇이 더 성능이 좋은지 궁금할 수 있습니다. 다음 기능은 동일한 작업을 수행합니다.
def append(alist, iterable):
for item in iterable:
alist.append(item)
def extend(alist, iterable):
alist.extend(iterable)
시간을 정합시다.
import timeit
>>> min(timeit.repeat(lambda: append([], "abcdefghijklmnopqrstuvwxyz")))
2.867846965789795
>>> min(timeit.repeat(lambda: extend([], "abcdefghijklmnopqrstuvwxyz")))
0.8060121536254883
타이밍에 대한 의견 다루기
한 댓글 작성자는 다음과 같이 말했습니다.
완벽한 대답, 한 요소만 추가해서 비교하는 타이밍이 그리워
의미상 올바른 일을 하십시오. iterable의 모든 요소를 추가하려면 extend
. 하나의 요소만 추가하는 경우 append
.
자, 제 시간에 이것이 어떻게 작동하는지 알아보기 위해 실험을 만들어 보겠습니다.
def append_one(a_list, element):
a_list.append(element)
def extend_one(a_list, element):
"""creating a new list is semantically the most direct
way to create an iterable to give to extend"""
a_list.extend([element])
import timeit
그리고 단지 확장을 사용하기 위해 이터러블을 만드는 것이 (사소한) 시간 낭비라는 것을 알았습니다.
>>> min(timeit.repeat(lambda: append_one([], 0)))
0.2082819009956438
>>> min(timeit.repeat(lambda: extend_one([], 0)))
0.2397019260097295
우리는 추가할 요소 가 하나만extend
있을 때 사용하여 얻을 수 있는 것이 없음을 이것으로부터 배웁니다 .
또한 이러한 타이밍은 그다지 중요하지 않습니다. 나는 단지 파이썬에서 의미론적으로 올바른 일을 하는 것이 옳은 일을 하는 것이라는 요점을 알려주기 위해 그들에게 보여주고 있는 것 입니다 .
두 개의 비교 가능한 작업에서 타이밍을 테스트하고 모호하거나 반대의 결과를 얻을 수 있습니다. 의미상 올바른 일을 하는 데만 집중하세요.
결론
iterable의 각 요소 를 목록에 추가하려는 경우 의미상 더 명확하고 , extend
보다 훨씬 빠르게 실행할 수 있습니다 .append
목록에 추가할 단일 요소(이터러블이 아님)만 있는 경우 append
.