Python/2.7 information

다차원 리스트를 만들고 복사하는 것에 대해서.

qkqhxla1 2016. 11. 8. 12:53

파이썬에서 다차원 리스트는 여러가지 방법으로 만들수 있다.


5칸의 1차원 리스트는 아래와 같이 만들수 있다.


a = [0 for i in xrange(5)] 또는 a = [0]*5.


5*5칸의 2차원 리스트는 아래와 같이 만들수 있다.


a = [[0 for j in xrange(5)] for i in xrange(5)] 또는 a = [[0]*5]*5


파이썬을 많이 안써본 분들은 오 후자가 더 짧고 좋네. 전자는 버리고 후자만 외워둬야지. 하겠지만


난 주로 전자의 방법을 쓴다. 후자는 안 쓰는 편이다. 이유는 후자처럼 다차원 리스트를 만들면


리스트가 제대로 복사가 안되기 때문이다.


1차원 리스트는 문제가 없다.

a = [0]*5
a[1] = 1
print a

a = [0 for i in xrange(5)]
a[1] = 1
print a

출력을 해보면 동일하게 의도한대로 출력된다. 


2차원 이상부터는 내부는 깊은 복사가 안되고 얕은 복사만 되는 듯 싶다.

a = [[0]*5]*5
a[1][1] = 1
print a

a = [[0 for j in xrange(5)] for i in xrange(5)]
a[1][1] = 1
print a

돌려보면 알겠지만 두개의 출력 결과가 다르다. 얕은 복사가 되서 하나를 바꾸면 다른 하나도 바뀐다고


추측해볼수 있다. 그런데 또 리스트의 가장 마지막 부분에는 *5처럼 만들어도 깊은 복사가 되는 모양이다.

# -*- encoding: cp949 -*-
a = [[0]*5]*5
a[1][1] = 1
print a

a = [[0 for i in xrange(5)]]*5
a[1][1] = 1
print a

print;print

a = [[0]*5 for i in xrange(5)]
a[1][1] = 1
print a

a = [[0 for j in xrange(5)] for i in xrange(5)]
a[1][1] = 1
print a

한개씩 넣어봤는데 위쪽은 제대로 안됬고, 아랫쪽은 의도한대로 나온다.


결론 : 다차원 리스트를 만들기 위해서는 길더라도 저렇게 만들자.


그리고 다차원 리스트를 복사시 copy모듈을 쓸수 있다. 그런데 여기서 또 주의해야한다.


copy.copy는 얕은 복사이고 copy.deepcopy는 깊은 복사이다. 얕은 복사로 리스트를 복사할경우


중간에 리스트 값이 바뀌면 원래의 리스트도 바뀐다는 사실.


그리고 a가 리스트라고 하면 b = a[:]처럼 리스트를 복사할 수 있는데 이것도 동작이 오묘하다.


a가 1차원 리스트일경우 b는 깊은복사처럼 복사가 되지만 a가 2차원리스트일경우 b는 얕은 복사가 된다.

# -*- encoding: cp949 -*-
a = [0 for i in xrange(5)]
b = a[:]
a[1] = 1
print a
print b #깊은복사처럼 제대로 나옴.

print

a = [[0 for j in xrange(5)] for i in xrange(5)]
b = a[:]
a[1][1] = 1
print a 
print b #a만 바꿨는데 b의 1,1도 1로 바뀌어있음.

print

import copy
a = [[0 for j in xrange(5)] for i in xrange(5)]
b = copy.deepcopy(a)
a[1][1] = 1
print a 
print b #깊은복사가 제대로 됨.

2차원이상의 리스트를 복사할때 [:]말고 copy.deepcopy를 쓰면 제대로 복사가 된다. 


파이썬이 편하긴 한데 이런 오묘한 문제를 볼땐 좀 불편하다.



결론.

1.리스트 생성시 [0 for i in xrange(5)] 처럼 만들어야 안심됨.

2.리스트 복사시 copy.deepcopy의 깊은 복사를 하자.


추가.

mutable과 immutable의 차이 때문에 생긴다고 함.

http://ledgku.tistory.com/54