Post

3주 - 궁금한 점 추가 공부

파이썬 추가 공부

파이썬을 공부하던 중 이해가 쉽게 안되서 따로 정리하는 글입니다.

범위 자료형은 어째서 자료형인가?

딕셔너리는 순서없는 자료형인가?

인덱스로 사용 불가한가?

왜 리버스함수를 사용한 리스트 객체만이 이터레이터를 사용할 수 있는가? 슬라이싱은?

그리고 그냥 리스트는 불가한건가?

이런 내용들이 궁금해서 따로 적어봅니다.

저 같은 바보가 아니라면 그냥 넘어가 주세요

범위 자료형은 어째서 자료형인가?

공부하다 문득 생각났습니다.

범위 자료형은 자료형이라지만 range()만 보면

그냥 범위내 정수만 생성해주는 그냥 정수 생성함수 아닌가? 하는 생각말이죠.

결론부터 말씀드리자면 자료형이 맞다고 합니다.

간단한 예제로 확인해보면

1
2
r = range(10)
print(type(r))  # <class 'range'>

range타입이 따로 정해져있는 자료형이 맞다는 겁니다.

아니 그래도 자료”형” 이라면서 데이터 형식은 아닌데?

클래스만 존재하는거 아님? 할 수도 있지만

리스트와 달리 미리 생성하고 저장하지 않고

필요할때만 생성해서 사용하는 “효율적인” 자료형으로 생각하면 됩니다.

1
2
3
4
5
r = range(1, 1000000)  # 아직 생성안됨
l = list(range(1, 1000000))  # 생성 후 리스트로 저장함

print(r)  # range(1, 1000000) 그대로 출력됨
print(l[:5])  # [1, 2, 3, 4, 5] 저장된걸 꺼내쓴다.

딕셔너리는 왜 숫자로 호출하지 못하는가?

앞서 딕셔너리를 배울때 분명히 key로 값을 호출하면 된다 했는데 어째서 이런 멍청한 질문을 하느뇨? 할 수 있습니다.

하지만…. 딕셔너리에 순서가 존재하는데 호출을 못하니 너무 궁금하잔아요…

순서들이 존재함에도 우리는 호출하지 못하고 어째서 키로만 호출해야할까요?

이는 해시테이블기반으로 설계되어 특정한 키를 빠르게 검색하는데 최적화 되어있는 자료구조이기 때문입니다.

(하나하나 순차적으로 연결되어 있다 생각해주세요)

리스트의 경우 메모리에 순서대로 적재됨으로써 인덱스기반의 호출이 가능하지만

(해싱을 통해 버켓에 담기고 해싱을 통해 바로 접근가능)

딕셔너리의 경우 키를 해싱해서 랜덤한 메모리 주소로 변환하고 값을 그 메모리에 저장합니다.

따라서 메모리가 연속적이지 않아 인덱스로 접근이 불가능합니다.

(해싱 : 해싱함수를 통해 숫자를 변환시킵니다. 대충 글자를 랜덤한 메모리 주소로 변환시킨다고 생각)

하지만 리스트와 달리 처음부터 순차적으로 값을 찾아야 하는게 아닌 해싱을 통해 값을 찾기 때문에 검색을 빠르게 할 수 있게 됩니다.

결론 : 딕셔너리는 리스트와 달리 연속된 메모리로 저장되지 않아서 순서를 인덱스로 호출이 불가능하다.

이터레이터란?

뜻은 값을 하나씩 순차적으로 꺼낼 수 있고 반복되는 객체인데….

어라? 그럼 리스트도 이터레이터 객체 아닌가?

값을 순차적으로 꺼낼 수 있고 반복되는 객체도 맞는데?

1
2
3
4
5
6
7
8
9
10
11
12
13
numbers = [1, 2, 3, 4, 5, 6]

print(next(numbers))
print(next(numbers))
print(next(numbers))
print(next(numbers))
print(next(numbers))

Traceback (most recent call last):
  File "/home/han/project/4장.py", line 307, in <module>
    print(next(numbers))
          ^^^^^^^^^^^^^
TypeError: 'list' object is not an iterator

네 아닙니다….. 우째서 리스트는 이터레이터가 아닌가요?

이유는 단순합니다. 리스트 안에 next메서드가 없기때문에 이터러블이지만 이터레이터는 아닙니다.

그래서 이터레이터로 사용하고 싶다면 따로 iter()함수를 사용하여 이터레이터 객체로 만들어서 사용해야합니다.

1
2
3
4
5
6
7
8
numbers = [1, 2, 3, 4, 5, 6]
itrnumbers = iter(numbers)

print(next(itrnumbers)) #1
print(next(itrnumbers)) #2 
print(next(itrnumbers)) #3
print(next(itrnumbers)) #4
print(next(itrnumbers)) #5

결론 : 이터러블한 객체 중 내부에 next메서드가 있는 객체만이 이터레이터가 된다!

그럼 reversed와 동일하게 리스트를 반대로 만드는 [::-1]슬라이싱은 어떨까요?

1
2
3
4
5
6
7
8
9
10
11
12
13
numbers = [1, 2, 3, 4, 5, 6]
numbers= numbers[::-1]
print(next(numbers)) 
print(next(numbers)) 
print(next(numbers)) 
print(next(numbers)) 
print(next(numbers)) 

Traceback (most recent call last):
  File "/home/han/project/4장.py", line 333, in <module>
    print(next(numbers)) 
          ^^^^^^^^^^^^^
TypeError: 'list' object is not an iterator

네 보다싶이 리스트라서 이터레이터가 안된다고 나옵니다.

이유는 슬라이싱의 경우 새롭게 리스트를 만들어내는거라 이터레이터 객체를 만들어 반환하는 리버스와 달리 그냥 리스트 객체인지라 이터레이터가 되지 않습니다.

This post is licensed under CC BY 4.0 by the author.

Trending Tags