2020년 2학기 파이썬 첫 스터디 멘토링
동아리 내 스터디에 멘토로 참가했는데, 첫 스터디에서 다룬 내용들을 정리해봤다. 어쨰 그룹 과외가 된 느낌이지만... 혼자서 공부하기엔 어려운 개념들이 있어서 설명해줬다.
아래는 시간상 듣지 못한 사람들을 위한 수업 정리글이다.
중급반이므로 생활코딩 사이트 ( opentutorials.org/course/1750/9620 ) 기준으로 조건문과 그 위쪽은 생략하기로 했습니다.
오늘 스터디에서는 타입, 리스트, dict 타입, 반복자(Iterator)와 객체 지향의 기본적인 개념에 대해서 다루었는데요, list 와 dict는 파이썬의 내장 자료형인데, 타입에 대해선 간단하게 언급만 했고요, 그 다움에 list / dict의 문법과 특징에 대해서 짧게 설명했습니다.
우선 list
의 기본 개념은 학교 수업 덕분에 다들 알고 계셔서 넘어갔습니다.
list
의 특징으로 다룬 건 원소의 타입에 관한 건데요, 파이썬에서의 list
는 원소의 타입이 서로 달라도 됩니다. 예를 들어
l = ['str', 1, None, [1]]
같은 경우 원소의 타입은 첫번째부터 차례대로 문자열, 숫자, None (특수 타입), list입니다. C 등의 언어와 다른 점이라 헷갈릴 가능성이 있을 것 같아서요.
학교 수업이 dict에 대해서 많이 가르치지 않기에 dict에 대해선 좀 더 설명했는데요,
var = {}
이런 식으로 빈 dict
를 초기화할 수 있고,
var = {
'a': 'b'
}
var['a'] = 'c'
print(var['a'] )
이런 식으로 dict
를 초기화하거나 접근, 수정할 수 있습니다.
dict
의 키가 숫자일 수도 있는데요, 값이 중간에 비어있는 경우 list
보다 dict
가 효율적일 수 있습니다.
d = {
100000000000: 1
}
이런 코드의 경우 배열로 표현하면 매우 많은 원소가 필요하기 때문에 메모리도 많이 먹꼬 성능도 떨어지게 됩니다.
두번째로 반복자의 개념에 대해서 다뤘습니다. 학교 수업에선 배열과 range
만 가르치는데, 실제 구현에 관련된 iterator도 이해하고 넘어가야 하는 개념이거든요.
for key in dictionary.keys():
pass
iterator는 다음 원소를 뱉는 기능이 있는 함수로 생각하시면 됩니다. 인터페이스라고 얘기하긴 했지만, 핵심적인 함수가 한 개뿐인 인터페이스인지라 그냥 함수라고 생각하셔도 됩니다. (실제로 함수 선언만으로 iterator 인터페이스를 구현할 수 있습니다).
이 개념이 왜 중요하냐면,
for key in range(100000000000000):
pass
위와 같은 코드가 메모리 부족 오류가 뜨지 않고 잘 실행되는 원리를 알아야 하기 때문입니다. 만약 range(100000000000000)
이 배열을 반환한다면, 원소의 개수가 100000000000000개인 배열을 할당해야 하는데, 그려면 최소 90 테라 바이트의 메모리가 필요합니다. 그런데 실제로는 그런 일이 일어나지 않죠. 그게 iterator의 핵심입니다.
그 뒤엔 객체 지향의 개념에 대해 얘기했습니다. 인터페이스는 간단히 말해 특정 기능들의 집합입니다.
주의해야 할 점은 파이썬에 인터페이스는 존재하지 않는다는 점입니다. 그럼에도 인터페이스라고 표현한 건 인터페이스를 정의하는 문법이 없을 뿐, 암시적(implicit)인 인터페이스는 많이 쓰이기 때문입니다.
class Car:
def wheels(self):
return 4
이런 식으로 클래스를 정의하면
car = Car()
print(car.wheels())
처럼 쓸 수 있습니다. 그런데 생각해보면 모든 차의 바퀴가 4개인 건 아니죠. 이럴 땐 해결할 방법이 여러가지 있습니다.
우선 클래스를 만들 때 인자로 받는 방법이 있습니다.
class Car:
def __init__(self, wheels):
self.num = wheels
def wheels(self):
return self.num
bike = Car(2)
normalCar = Car(4)
클래스가 변수를 묶어준다는 개념으로 사용하는 경우인데요, dict
로도 변수를 묶어줄 수 있지만, 클래스를 사용하면 아래 코드에 비해 큰 장점이 있습니다.
bike = {'wheels': 2}
normalCar = {'wheels': 4}
이런식으로 짜는 것에 비해 오타로 인해 문제가 발생할 가능성이 현저히 줄어든다는 게 그 장점입니다.
오버라이딩은 이번 주 스터디에서 다룰 내용이 아니었기에 넘어갔습니다.
다른 방법은 인터페이스 비슷한 걸 사용하는 방법입니다. 엄밀히 말하면 파이썬엔 인터페이스가 없지만, 암시적(implicit)인 인터페이스는 만들 수 있습니다.
class Bike:
def wheels(self):
return 2
class BigTruck:
def wheels(self):
return 8
# car = Bike()
# car = BigTruck()
car.wheels()
이 코드에서 주석을 하나씩 해제해보면 인터페이스의 기본 원리를 알 수 있습니다.
car
이라는 변수가 Bike
인지, BigTruck
인지 알 필요 없다는 게 인터페이스의 핵심입니다.
마지막으로 질문 있으면 언제든지 톡 주세요. 이 방에 올리셔도 되고 갠톡으로 질문하셔도 됩니다.