리스트 생성에 대한 설명보완이 필요합니다.
, J SM님이 작성 지뢰찾기 예제를 푸는데 아래와 같이 첫부분 코드를 짰더니
m = []자꾸 sol[0][1]+=1 하는 과정에서 [0][1]뿐 아니라 [1][1],[2][1]의 값까지 같이 바뀌는 문제가있어 이해가 안되어 간단히 아래와 같이 실험을 해보았더니
a, b = map(int, input().split())
sol = [[0] * a] * b
for i in range(a):
m.append(list(input()))
>>> sol=[[0]*3]*3책의 예제처럼 그냥 곱하기를 써서 만들면 위에서 볼수있듯이 아예 두 행을 같은 객체로 인식해버리는듯 합니다. 행도 마찬가지여서 [0]*2로 만들면 sol[0][1] is sol[0][2]에서 True가 뜹니다. 그러나 같은 행에서는 sol[0][1]에 값을 넣는다고 sol[0][2]까지는 바뀌지는 않습니다.근데 왜
>>> sol
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> sol[0][1]+=1
>>> sol
[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
>>> sol[0][1]
1
>>> sol[0][1]=sol[0][1]+1
>>> sol
[[0, 2, 0], [0, 2, 0], [0, 2, 0]]
>>> sol[0][1]=3
>>> sol
[[0, 3, 0], [0, 3, 0], [0, 3, 0]]
>>> sol[0] is sol[1]
True
>>> sol=[[0]*3 for i in range(3)]
>>> sol
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> sol[0] is sol[1]
False
>>> sol[0][1] is sol[0][2]
True
>>> sol[0][1]=1
>>> sol
[[0, 1, 0], [0, 0, 0], [0, 0, 0]]
>>> sol[0][1]=sol[0][1]+1
>>> sol
[[0, 2, 0], [0, 2, 0], [0, 2, 0]]
이부분은 이렇게 될까요? 도저히 이게 이해가 되지 않는데 설명좀 해주시면 감사하겠습니다 ㅠㅠㅠ
더불어, 아래의 코드로 테스트 케이스 예제 답이 잘 나오는데 심사에 자꾸 통과를 못하는데 혹시 이유를 알 수 있을까요?ㅠㅠ
해설과 좀 다르게 접근해서 map을 훑으며 지뢰가 나오면 sol 이란 0으로 초기세팅된 리스트에다 8방의 값을 1씩 증가시켜주는 원리로, 테스트 케이스는 똑같이 잘 나옵니다.
m = []
a, b = map(int, input().split())
sol=[[0 for i in range(a)] for j in range(b)]
for i in range(a):
m.append(list(input()))
for i in range(a):
for j in range(b):
if m[i][j] == '*':
for k in range(-1, 2):
for l in range(-1, 2):
if i + k >= 0 and j + l >= 0 and i + k < a and j + l < b:
if m[i + k][j + l] != '*':
sol[i + k][j + l] += 1
else:
sol[i + k][j + l] = '*'
for i in range(len(sol)):
for j in range(len(sol[i])):
print(sol[i][j], end='')
print('\n')
Re: 리스트 생성에 대한 설명보완이 필요합니다.
, Chicken Chic님이 작성python list comprehension에서 [[0]*a]*b은 정의되어있지 않습니다. 저도 깊게 알진 않아 어째서 동작 할 수 있는진 모르겠지만, 해외 포럼에서도 위와 같은 방법은 예기치 못한 동작을 유발한다고 가능하면 쓰지 말라고 합니다.
또, 올려주신 코드에서
마지막 print('\n')이 문제입니다.
바로 앞, print(sol[i][j], end='')에 end를 붙인 이유를 생각하시면 답이 나오실 겁니다. 기본적으로 print()는 출력한 후 자동으로 개행해줍니다.
따라서, print('\n')는 개행을 두번 하기 때문에 심사문제 통과가 안되는 것입니다.
Re: 리스트 생성에 대한 설명보완이 필요합니다.
, J SM님이 작성그렇군요ㅠ 책에서 그렇게 만들길래 똑같이 동작하는건줄 알았는데.. C++랑 많이 다르네요. 줄바꿈도 printf("\n");로 했었는데 여긴 그냥 빈칸을 출력해서 띄워야하다니..
Re: 리스트 생성에 대한 설명보완이 필요합니다.
, 도장_ 관리자님이 작성해당 부분은 작가님의 검토를 거쳐서 반영하겠습니다.
a = [[0] * 2 for i in range(3)]
이러한 코드는 문제가 발생하지 않지만,
[ [0] * 3 ] * 3과 같이 작성한 코드는 내부에서 같은 리스트를 참조로 3번 넣었기 때문으로 보입니다. 즉, 리스트가 3개가 아니라 1개입니다.
326쪽 마지막에 설명된 코드 단축 부분은 삭제해야 할 것 같습니다.
불편을 드려 죄송합니다.
Re: 리스트 생성에 대한 설명보완이 필요합니다.
, 도장_ 관리자님이 작성해당 내용은 참조로 중복된 리스트를 생성하기 때문에 잘못된 내용입니다.
이에 해당 내용을 삭제했습니다. 종이책에서는 다음 중쇄에 반영될 예정입니다.
리스트 표현식으로 생성하는 것은 문제가 없지만, *을 이용해 생성하는 부분은 파이썬의 내부 동작이 다른 것 같습니다. 따라서 본문에서도 리스트 표현식으로 생성하는 부분은 그대로 남겨 두었고, *으로 축약하는 부분을 삭제했습니다.
이에 작가님의 검토를 거쳐 수정되었습니다.
문의에 감사드립니다.