23.03.24 TIL

최창수·2023년 3월 24일
0

문제: 두 리스트 비교

파이썬 코드를 작성하던 중 논리 오류가 발생하여 원인을 찾던 중 다음과 같은 코드가 문제가 됨을 알게 되었다.

a = [1, 2, 3, 4]
b = [i for i in range(1,5)]  # [1, 2, 3, 4]
if a is b:
	print('True')
else:
	print('False')
#출력 : False

두 list는 같은 위치의 모든 요소의 값이 같음에도 False를 출력하였다.

시도

1. 반복문

def is_list_same(a:list,b:list):
	if len(a)-len(b):
    	return False
    c=[]
    for i in range(len(a)):
    	c.append(a[i]-b[i])
    if not any(c):
    	return True
    return false
    

반복문을 이용한 방법은 가장 확실한 방법이다. 그러나 여러 내장함수를 사용하는 것에비애 현격히 느리고 코드도 길어지므로 채택하지 않았다.

2. ==

python에서 사용되는 is 대신 더 널리 쓰이고 python에서도 사용가능한 ==비교연산자를 사용하였다. 이를 통해 간단하고 빠르게 문제를 해결할 수 있었다.

b = [i for i in range(1,5)]  # [1, 2, 3, 4]
if a is b:
	print('True')
else:
	print('False')
#출력 : True

해결: ==is의 차이

검색결과==비교연산자는 값을 비교하고, is는 같은 객체인지를 확인하는 연산자임을 알 수 있었다. is는 같은 메모리상의 객체를 가리키고 있는 상태일 경우에만 True를 내보낸다 따라서 ==를 사용하면 된다.

배운점

객체와 is

다음의 python 코드에서 우리는 새로운 메모리 공간상에 또하나의 list를 새로 만들지 않고, 기존 list를 가르키는 새로운 pointer를 하나 만들게 된다.(shallow copy)

a = [1, 2, 3]
b=a

a와 b를 is로 비교하면 같은 객체이므로 True를 반환한다.
둘은 같은 객체이므로 a의 값을 편집하면 b의 값도 편집된다. 이를 간과하면 찾기 어려운 오류가 발생할 수 있다.
만약 a와 값이 같은 새로운 객체를 만들고 싶다면 다음과 같이 하면된다.

a = [1, 2, 3]
b=a[:]  # 처음부터 끝까지 요소를 전부 복사해온다

is 문의 일관성 없는 동작?

is문은 같은 메모리 내 객체인지를 확인하는 연산자 임에도 다음과 같이 동작할 수 있다.

a=10
b=10
print(a is b) #  True
>>> c = 100
>>> d = 100
>>> c == d
True
>>> c is d
True

분명 a-b, c-d는 코드상 다른 객체여야함에도 실제로는 True를 반환하는 이유는 실행시 작은 값의 int 객체들을 caching하여 각 int 변수들이 같은 수를 가리키면 같은 메모리상 공간을 가리키도록 지시하기 때문이다.

컨벤션 상 is의 사용 제한

is는 다음과 같은 상황을 제외하면 사용이 권장되지 않는다.

  1. 두 대상이 같은 객체임을 확인하고 싶을 때 사용한다.
  2. None과같이 singletion객체와의 비교에 사용한다.
    None은 singleton 객체중 하나이다. 싱글톤 객체는 메모리상에 단 하나의 인스턴스로 존재한다. 따라서 None과의 비교는 is를 써도 안전하다.

이 외에는 항상 ==를 쓰도록 한다.

학습: dictionary vs list

딕셔너리는 key-value 쌍을 hash-map에 저장한다. hash-map의 사용으로 인해 데이터를 조회, 저장하는 속도가 매우 빠르다. (시간복잡도가 1에 가까움). list는 linked list 형태로 데이터를 저장하며 대부분의 연산이 O(n)의 시간복잡도를 가져 딕셔너리보다 느리다. 따라서 만약 list를 사용할 때 중간 요소를 삭제할 일이 없다면 다음과 같은 딕셔너리로 대체하여 사용하는 것도 고려할 수 있다.

a={1:val1, 2:val2, ...}
profile
Hallow Word!

0개의 댓글