Using + and * with Sequence

JInwoo·2025년 2월 4일

Python의 squence 들은 +* operation을 지원한다. 이 때 주목 할 점은 +* 은 항상 새로운 object를 반환한다는 것이다.

l = [1, 2, 3]
l * 5 # [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3] is new object

다음은 *+ 사용 시 쉽게 할 수 있는 실수 이다.

weird_board = [['_'] * 3] * 3
weird_board
>>> [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]

weird_board[1][2] = 'O'
weird_board
>>> [['_', '_', 'O'], ['_', '_', 'O'], ['_', '_', 'O']]

weird_board 는 inner list 에 대한 세 개의 동일한 reference를 3 개 만들었다. 따라서 weired_board 의 inner list 중 한 개의 item을 변경하면 모든 inner list의 item이 변경된다. 위 코드는 아래와 같다.

board = []
row = ['_'] * 3
for i in range(3):
    board.append(row)
board
>>> [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]

Augmented Assignmnet with Sequences

+= 또는 *= 과 같은 augmented assignment operator 들 역시 sequences에 적용 가능하다. 이 떄 augmented assignment operator 가 new object를 반환 하는지, in-place operator가 되는 지는 sequence object가 __iadd__ 또는 __imul__ special method를 구현 했는지 여부에 달려있다. python 에서는 += operator 수행 시 __iadd__ special method가 호출 되고 만약 __iadd__ 가 구현되어 있지 않으면 __add__ 를 호출한다. 앞서 말한 것처럼 sequence의 + 는 항상 new object를 반환한다. 따라서 __iadd__ 가 구현되어 있지 않다면, += 는 in-place 방식이 아닌 new object를 반환한다. *= 에도 동일한 논리가 적용된다. list 처럼 mutable sequence인 경우 __iadd__, __imul__ 이 구현되어 있고, tuple 처럼 immutable sequence 인 경우 __iadd__, __imul__ 이 구현되어 있지 않다.

l = [1, 2, 3]
idl = id(l)
l *= 2
id(l) == idl  # same list
>>> True

t = (1, 2, 3)
idt = id(t)
t *= 2
id(t) == idt  # new tuple
>>> False

Reference

Luciano Ramalho, Fluent Python, 2nd Edition, O'Reilly Media, Inc., April 2022

profile
Jr. AI Engineer

0개의 댓글