파이썬 ps를 하면서 많이 하기 쉬운 실수들에 대해 적는다.
다음 두 코드의 결과는 어떻게 될까?
하나는 맞고 하나는 이상한 결과를 배출한다.
1)
class Solution(object):
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
results = []
def dfs(nums, k, pos, subsets=[]):
if k == 0:
results.append(subsets)
return
for i in range(pos, len(nums)):
subsets.append(nums[i])
dfs(nums, k - 1, i + 1, subsets)
subsets.pop()
for i in range(len(nums) + 1):
dfs(nums, i, 0, [])
return results
sol = Solution()
print(sol.subsets(nums=[1, 2, 3]))
2)
from typing import List
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
results = []
def subset(pos, n, arr):
if pos == n:
return results.append(arr)
subset(pos+1, n, arr + [nums[pos]])
subset(pos+1, n, arr)
subset(0, len(nums), arr=[])
return results
sol = Solution()
print(sol.subsets(nums=[1, 2, 3]))
1) 코드의 결과
2) 코드의 결과
그 이유는 바로 append에 있다.
1) 코드를 보면, dfs 함수에서 subsets의 주소값을 참조해서 results에 append했다.
하지만 subsets는 dfs 안에서 for문이 돌 때마다 계속 수시로 변화한다.
그리고 맨 마지막에는 subsets는 []이 된다.
그렇기 때문에 최종적으로는 []이 출력되게 된다.
왜냐면 results에 append 된 값은 각각의 []의 주소값을 참조하도록 되어있기 때문이다.
그림으로 표현하면 다음과 같다.
첫 번째 if 통과 후 나온 어떤 list가 subsets를 참조하고,
두 번째 if 통과 후 나온 어떤 list가 subsets를 참조하고...
이렇게 각 과정에서 같은 subsets를 가리키도록 저장된다.
하지만 우리가 원하는 결과는 아래와 같은 형태이다.
즉, 주소값이 아닌, 값을 복사하려면
1) [:] 쓰기
results.append(subsets[:])
2) copy() 사용 (단, 2차원 이상의 list일 경우 deepcopy()를 써야 함)
results.append(subsets.copy())
그렇다면 2번째 코드는 왜 정상으로 작동할까?
그 이유는 subset 함수 내에 arr을 매번 호출했기 때문이다.
따라서 각각의 함수에서는 서로 다른 arr이 전달됐을 것이고, 그 결과를 results에 저장해줬기 때문에
우리가 원하는 대로 output이 나온다.
'Computer Science > Python' 카테고리의 다른 글
Python 딕셔너리 정렬 (Key, Value 기준 sort) (1) | 2022.04.09 |
---|---|
python list append() vs extend() 차이 (0) | 2021.01.31 |
[Python] is 와 == 의 차이 (0) | 2021.01.26 |
[파이썬] 클래스 변수 vs 인스턴스 변수 차이 (0) | 2021.01.12 |