파이썬 모듈은 함수와 클래스, 변수들의 조합이다.
파이썬은 함수와 클래스를 더 쉽게 사용하기 위해 모듈을 사용한다.
모듈을 프로그램에 임포트하면 거기에 담긴 모든 것들을 사용할 수가 있다.
파이썬은 여러 가지 작업들을 위한 모듈들을 많이 가지고 있다.
여기에서 몇 가지 유용한 파이썬 모듈과 해당 모듈에 들어있는 함수들을 살펴볼 것이다.
(보고 싶은 항목만 클릭해서 읽으면 된다.)
COPY 모듈을 사용해 복사본 만들기
copy 모듈은 객체의 복사본을 생성하는 함수들을 가지고 있다.
대게 프로그램을 만들 때 새로운 객체를 생성하지만, 가끔은 객체의 복사본을 생성하고 새로운
객체를 생성하기 위해 그 복사본을 사용하는 것이 유용하다.
여러 단계를 가지는 객체를 생성할 때 특히 더 그렇다.
예를 들어 name, number_of_legs, color 매개변수를 받는
__init__ 함수가 있는 Animal 클래스가 있다고 치자.
다음의 코드를 사용해 Animal 클래스의 새로운 객체를 생성할 수 있다.
class Animal: def __init__(self, species, number_of_legs, color): self.species = species self.number_of_legs = number_of_legs self.color = color
자, 이름이 harry인 다리가 6개 있는 핑크색 히포그리프(hippogriff, 말의 몸에 독수리 머리와 날개를 가진 전설 속 괴물)을 만들어보자.
harry = Animal('hippogriff', 6, 'pink')
만약에 6개의 다리를 가진 핑크색 히포그리프들의 무리를 만들고 싶다면 어떻게 해야 할까?
앞의 코드를 여러 번 반복해서 생성할 수도 있겠지만, 다음과 같이 copy 모듈에 있는 copy를 사용할 수도 있다.
>>> import copy >>> harry = Animal('hippogriff', 6, 'pink') >>> harriet = copy.copy(harry) >>> print(harry.species) hippogriff >>> print(harriet.species) hippogriff
이 예제에서는 객체를 생성하고 harry라는 변수에 담은 다음,
그 객체의 복사본을 생성하여 harriet라고 한다.
이 두 개의 객체들은 완전히 다른 객체다(다만, 같은 종일 뿐이다).
이렇게 하면 약간의 타이핑을 줄여준다.
하지만 객체가 매우 많이 복잡해진다면 복사할 수 있다는 것이 훨씬 더 유용할 것이다.
>>> harry = Animal('hippogriff', 6, 'pink') >>> carrie = Animal('chimera', 4, 'green polka dots') >>> billy = Animal('bogill', 0, 'paisley') >>> my_animals = [harry, carrie, billy] >>> more_animals = copy.copy(my_animals) >>> print(more_animals[0].species) hippogriff >>> print(more_animals[1].species) chimera
첫 번쨰 세 줄에서는 세 개의 Animal 객체를 생성하고 각각을 harry와 carrie, billy에 담는다.
네 번째 줄에서 그 객체들을 my_animals라는 리스트에 추가한다.
다음으로, copy를 사용해 새로운 리스트인 more_animals를 만든다.
마지막으로, my_animals 리스트에 있는 두 개의 객체([0]과 [1])의 종을 출력해 원래 있던 리스트의 것
(hippogriff와 chimera)과 같은지를 확인한다.
객체들을 다시 생성하지 않고 리스트의 복사본을 만든 것이다.
만약에 원본 리스트인 my_animals에 있는 Animal 객체 중의 하나의 종을 변경한다면
(hippogriff를 ghoul로) 어떻게 될까?
파이썬은 more_animals에 있는 것도 변경한다.
>>> print(my_animals[0].species) ghoul >>> print(more_animals[0].species) ghoul
참 이상하다.
my_animals의 종만 바꾸지 않았나?
왜 두 리스트 모두의 종이 변경된 것일까?
종이 바뀐 이유는 copy가 사실상 얕은 복사(shallow copy)를 만든 것이기 때문이다.
이 말은 여러분이 복사했던 객체들의 안에 있는 객체들을 복사하지 않았음을 의미한다.
여기서는 메인 list 객체를 복사했지만, 리스트 안에 있는 각각의 객체들을 복사한 것은 아니다.
우리는 새로운 객체들을 가지지 않은 새로운 리스트를 갖게 되며, 그 리스트인 more_animals는 그 안에 동일한 세 개의 객체들을 갖는다.
마찬가지 이유로, 새로운 동물을 첫 번째 리스트(my_animals)에 추가하면 복사본(more_animals)에는 나타나지 않는다.
그것을 확인하기 위해서 다음과 같은 다른 동물을 추가한 다음에 리스트의 길이를 출력해보자.
>>> sally = Animal('sphinx', 4, 'sand') >>> my_animals.append(sally) >>> print(len(my_animals)) 4 >>> print(len(more_animals)) 3
여기서 알 수 있듯이, 첫 번째 리스트인 my_animals에 새로운 동물을 추가하면 그 리스트의 복사본인
more_animals에는 추가되지 않는다. len을 사용해 결과를 출력하면 첫 번째 리스트는 네 개의 요소를 가지며,
두 번째 리스트는 세 개를 가진다.
copy 모듈에 있는 다른 함수인 deepcopy는 복사된 객체 안에 있는 모든 객체의 복사본을 실제로 생성한다.
my_animals를 복사하는 데 deepcopy를 사용하면 모든 객체들의 복사본을 가진 완벽한
새로운 리스트를 갖게 된다. 그 결과, 원본 Animal 객체들 중의 하나를 변경하면 새로운 리스트에 있는 객체들에는
영향을 미치지 않는다.
다음의 예제를 살펴보자.
>>> more_animals = copy.deepcopy(my_animals) >>> my_animals[0].species = 'wyrm' >>> print(my_animals[0].species) wyrm >>> print(more_animals[0].species) ghoul
원본 리스트의 첫 번째 객체의 종을 ghoul에서 wyrm으로 변경했지만 복사된 리스트는 변경되지 않는다.
각각의 리스트에 있는 첫 번째 객체의 종을 출력해보면 확인할 수 있다.
KEYWORD 모듈로 키워드 추적하기
파이썬 키워드(keyword)는 if와 else, for처럼 파이썬 언어 자체의 일부인 어떤 단어다.
keyword모듈은 iskeyword라는 이름의 함수와 kwlist라는 변수를 가지고 있다.
iskeyword 함수는 어떤 문자열이 파이썬 키워드일 경우에 참을 반환하며,
kwlist 변수는 모든 파이썬 키워드들의 목록을 반환한다.
다음 코드에서 iskeyword 함수는 if라는 문자열에 참을 반환하고,
ozwald라는 문자열에 거짓을 반환한다. kwlist 변수에 있는 내용을 출력해보면 전체 키워드 목록을 볼 수 있다.
이것은 매우 유용하다. 왜냐하면 키워드들은 가끔씩 변경되기 때문이다.
파이썬의 새로운 버전 (또는 이전 버전)은 또 다른 키워드들을 가지고 있을 수 있다.
>>> import keyword >>> print(keyword.iskeyword('if')) True >>> print(keyword.iskeyword('ozwald')) False >>> print(keyword.kwlist) ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] >>>
RANDOM 모듈로 랜덤 숫자 얻기
random 모듈은 컴퓨터에게 "숫자 하나를 뽑아줘."라고 말하는 것과 같은 난수(random number)를 생성하는 데 유용한 많은 함수들을 가지고 있다.
random 모듈에 있는 가장 유용한 함수는 randint와 choice, shuffle이다.
- 난수를 뽑기위해 RANDINT 사용하기 -
randint 함수는 1부터 100 사이나 100부터 500 사이 또는 1000부터 5000 사이처럼
어떤 숫자의 범위 안에서 난수를 뽑아낸다. 다음 에제를 살펴보자.
>>> import random >>> print(random.randint(1, 100)) 85 >>> print(random.randint(100, 1000)) 925 >>> print(random.randint(1000, 5000)) 3200
다음과 같이 while 루프를 사용해 간단한 숫자 맞푸기 게임을 만들 때 randint를 사용할 수 있다.
>>> import random >>> num = random.randint(1, 100) >>> while True: print('Guess a number between 1 and 100') guess = input() i = int(guess) if i == num: print('You guessed right') break elif i < num: print('Try higher') elif i > num: print('Try lower')
먼저 random 모듈을 임포트하고 num 변수에 1부터 100 사이의 난수를 randint로 생성해 설정한다.
그리고 영원히 돌아가는 (즉, 플레이어가 숫자를 맞출 때까지 돌아가는) while 루프를 만든다.
다음으로 메시지를 출력하고 사용자로부터 값을 입력받기 위해 input을 사용한다.
이것은 guess 변수에 저장한다.
우리는 입력된 값을 int를 사용하여 변환한 다음, 변수 i에 저장한다.
그런 다음에 랜덤하게 선택된 숫자와 비교한다.
만약에 입력된 값과 랜덤하게 선택된 숫자가 같다면 "You guessed right"이라고 출력하고 루프를 빠져 나온다.
만약에 같지 않다면 사용자가 입력한 값이 난수보다 큰지를 검사하고
작은 지도 검사한다. 그리고 그에 맞는 적절한 힌트 메시지를 출력한다.
이 코드는 약간 길기 때문에 새로운 쉘 창에 입력하거나 텍스트 문서를 만들고 저장해서 IDLE에서 실행하면 좋을 것이다.
다음은 저장된 프로그램을 열고 실행하는 방법이다.
1. IDLE 을 실행하고 File > Open.., 을 선택한다.
2. 파일을 저장해놓은 디렉토리로 이동해 파일을 선택한ㄷ3ㅏ.
3. Open(열기) 버튼을 클릭한다.
4. 새로운 창이 열리면 Run > Run Module 을 선택한다.
리스트에서 항목을 무작위로 뽑기 위해 CHOICE 사용하기
만약에 주어진 범위에서 난수를 선택하는 것이 아니라, 리스트에서 무작위로
항목을 뽑고 싶다면 choice를 사용할 수 있다. 예를 들어 여러분을 위한 디저트를 파이썬이
골라주도록 할 수 있다.
>>> import random >>> desserts = ['ice cream', 'pancakes', 'brownies', 'cookies', 'candy'] >>> print(random.choice(desserts)) cookies
나는 디저트로 쿠키가 선택된 것 같다. 전혀 나쁘지
리스트를 섞기 위해 SHUFFLE 사용하기
shuffle 함수는 리스트에 있는 항목들을 섞는다. 만약에 여러분이 IDLE을 가지고 작업하고 있었고,
이제 막 이전 예제의 random을 임포트하고 디저트 리스트를 만들었다면 다음의 코드에서
random.shuffle 명령줄을 삭제해도 된다.
>>> import random >>> desserts = ['ice cream', 'pancakes', 'brownies', 'cookies', 'candy'] >>> random.shuffle(desserts) >>> print(desserts) ['ice cream', 'brownies', 'cookies', 'candy', 'pancakes']
이 리스트를 출력하면 섞인 결과를 볼 수 있다.
순서가 완전히 바뀌었다. 만약에 카드 게임을 만들고 있다면 카드들을 나타내는 리스트를 섞을 때 이 함수를 사용할 수 있을 것이다.
SYS 모듈로 쉘 컨트롤하기
sys 모듈은 파이썬 쉘 자체를 컨트롤할 때 사용할 수 있는 시스템 함수들을 가지고 있다.
여기서는 exit 함수, stdin과 stdout 객체, version 변수를 어떻게 사용하는지 살펴볼 것이다.
- EXIT 함수로 쉘 종료하기 -
exit 함수는 파이썬 쉘이나 콘솔을 멈추는 방법이다.
다음의 코드를 입력하면 정말로 종료하고 싶은지를 묻는 다이얼로그가 나타날 것이다.
Yes를 클릭하면 쉘이 종료된다.
>>> import sys >>> sys.exit()
- STDIN 객체로 읽기 -
sys 모듈의 stdin 객체 (standard input의 약자)는 사용자가 쉘에 입력한 것을 읽어서
프로그램에서 사용할 수 있도록 해준다, 이 객체는 엔터를 누를 때까지 키보드로 입력한
텍스트 라인을 읽는 readline 함수를 가지고 있다.
>>> import sys >>> v = sys.stdin.readline() He who laughs last thinks slowest >>> v 'He who laughs last thinks slowest\n'
파이썬은 변수 v 에 He Who laughs last thinks slowest라는 문자열을 저장했다.
input 함수와 readline 함수의 차이점중 하나는 readline 함수는 매개변수로 지정된 글자수 만큼 읽어 들인다는 것이다.
예를 들면 다음과 같다.
>>> v = sys.stdin.readline(13) He who laughs last thinks slowest >>> print(v) He who laughs
- STDOUT 객체로 쓰기 -
stdin 객체와는 달리, stdout 객체(standard output의 약자)는 쉘(또는 콘솔)에 메시지를 쓸 때 사용된다.
어떻게 보면 print 함수와 비슷하지만, stdout은 write와 같은 함수들을 가지고 있는 파일 객체다.
다음의 예제를 살펴보자.
>>> import sys >>> sys.stdout.write("what does a fish say when it swims into a wall?") what does a fish say when it swims into a wall?47
write가 끝날 때 쓰여진 글자 개수가 반환되는 것에 주목하자.
메시지의 끝에 출력된 52를 볼 수 있다.
화면에 얼마나 많은 글자를 썼는지 기록하기 위해서 이 값을 변수에 저장할 수도 있다.
- 내가 쓰는 파이썬 버전은? -
version 변수는 사용하고 있는 파이썬의 버전을 표시해주며 최신 버전을 사용하고 있는지를 확인하고자 할 때
유용할 수 있다. 어떤 프로그래머들은 그들이 만든 프로그램이 시작할 때 버전 정보를 보여주고 싶어한다.
예를 들어 다음과 같이 프로그램에 파이썬 버전을 표시할 수도 있다.
>>> import sys >>> print(sys.version) 3.4.1 (v3.4.1:c0e311e010fc, May 18 2014, 10:38:22) [MSC v.1600 32 bit (Intel)]
TIME 모듈로 시간 작업하기
파이썬의 time 모듈은 시간을 표시하는 함수들을 가지고 있다. (어쩌면 여러분이 예상한 것과 다를 수도 있다.)
다음의 코드를 입력해보자.
>>> import time >>> print(time.time()) 1415091165.694159
time()을 호출하여 반환된 숫자는 1970년 1월 1일 00시 00분 00초 이후 지금까지의 초를 나타낸다.
이 자체로 볼 때 이 이상한 참조값은 직접적으로 유용해보이지 않을 수 있지만 사실은 도움이 된다.
예를 들어, 프로그램에서 실행하는 데 시간이 걸리는 부분을 알아보고자 할 때 시작 시간과
끝나는 시간을 기록하여 그 값들을 비교할 수 있다.
그렇다면 0부터 999까지 모든 숫자를 출력하는 데 걸리는 시간을 알아보도록 하자.
먼저 다음과 같은 함수를 만든다.
>>> def lots_of_numbers(max): for x in range(0, max): print(x)
그런 다음. time 모듈을 가지고 이 프로그램을 수정해 이 함수가 얼마나 시간이 걸리는지 알아보도록 하자.
>>> def lot_of_numbers(max): t1 = time.time() for x in range(0, max): print(x) t2 = time.time() print('it took %s seconds' % (t2-t1))
이 프로그램을 실행하면 다음과 같은 결과를 얻을 수 있다.
(이 값은 여러분의 시스템 속도에 따라 매우 다를 수 있다.)
0
1
2
3
.
.
997
998
999
it took 4.720006942749023 seconds
이 프로그램이 어떻게 동작하는지 살펴보자.
먼저 time() 함수를 호출하고, 반환된 값을 변수 t1에 할당한다.
그다음 루프를 돌며 숫자를 출력한다. 이 루프가 끝나면 다시 time() 함수를 호출하여
반환된 값을 변수 t2에 할당한다.
루프를 완료하는 데 몇 초가 걸렸기 때문에 t2에 있는 값이 t1보다 클 것이다.
왜냐면 1970년 1월 1일보다 더 시간이 지났기 때문이다.
t2에서 t1을 빼면 모든 숫자를 출력하는 데 걸린 시간을 얻을 수 있다.
- ASCTIME 으로 날짜 변환하기 -
asctime 함수는 튜플로 날짜(data)를 받아서 읽을 수 있는 어떤 것으로 변환한다
(튜플은 항목들을 가지고 있는 리스트와 같지만 변경할 수 없다는 것을 기억하자.)
아무런 매개변수 없이 asctime을 호출하면 읽을 수 있는 형태로 현재 날짜와 시간을 표시하게 될 것이다.
>>> import time >>> print(time.asctime()) Tue Nov 4 19:14:19 2014
매개변수로 asctime을 호출하려면 먼저 날짜와 시간에 대한 값으로 튜플을 생성한다.
예를 들어 튜플을 변수 t에 할당한다.
>>> t = (2007, 5, 27, 10, 30, 48, 6, 0, 0
이 값들은 년도와 월, 일, 시간, 분, 초, 요일(0은 월요일, 1은 화요일....), 일 년 중 며칠(우리는 0을 넣는다.),
일광 절약 시간인지 아닌지(만약에 아니라면 0, 맞다면 1)를 나타낸다. 다음과 같은
튜플로 asctime을 호출하면 다음과 같은 값을 얻게 된다.
>>> import time >>> t = (2020, 2, 23, 10, 30, 48, 6, 0 ,0) >>> print(time.asctime(t)) Sun Feb 23 10:30:48 2020
- LOCALTIME으로 날짜와 시간 얻기 -
asctime과 달리, localtime 함수는 현재 날짜와 시간을 객체로 반환한다.
이 값들은 asctime 입력 순서과 거의 같다.
만약ㅇ데 이 객체를 출력해본다면 클래스 이름과
tm_year(년), tm_mon(월), tm_mday(한 달 중 며 칠), tm_hour 등의 변수값을 볼 수 있을 것이다.
>>> import time >>> print(time.localtime()) time.struct_time(tm_year=2014, tm_mon=11, tm_mday=4, tm_hour=19, tm_min=21, tm_sec=14, tm_wday=1, tm_yday=308, tm_isdst=0)
현재 연도와 월을 출력하려면 이들의 인덱스 위치를 사용한다.(asctime에서 사용한 튜플처럼)
예제에서 year는 첫 번째 위치(인덱스 위치 0)이며 month는 두 번째 위치(인덱스 위치 1)이다.
따라서 우리는 year = t[0] 과 month = t[1]처럼 사용한다.
>>> t = time.localtime() >>> year = t[0] >>> month = t[1] >>> print(year) 2014 >>> print(month) 11 >>>
이렇게 하면 2020년의 두 번째 달임을 확인할 수 있다.
- SLEEP으로 잠깐 쉬기 -
sleep 함수는 프로그램에 약간의 딜레이를 주거나 천천히 동작하고자 할 때 매우 유용하다.
예를 들어 1에서 61까지 1초씩 출력하고자 할 때 다음과 같이 할 수 있다.
>>> for x in range(1, 61): print(x)
이 코드는 1부터 60까지의 모든 숫자를 빠르게 출력할 것이다.
하지만 파이썬에게 다음과 같이 하나 출력하고 1초씩 쉬라고 말할 수 있다.
>>> for x in range(1, 61): print(x) time.sleep(1)
이 코드는 각 숫자가 출력되는 사이에 딜레이를 추가한다.
정보를 저장하기 위해 PICKLE 모듈을 사용하기
pickle 모듈은 파이썬 객체를 파일로 쓸 수 있고 다시 쉽게 읽을 수 있는 어떤 것으로 변환해주는 데 사용된다.
여러분이 게임을 개발하고 있으며 플레이어의 진행 정보를 저장하고 싶다면 pickle이 유용하다는 것을
알게 될 것이다.
예를 들어 다음은 게임에 저장 기능을 추가한 것이다.
>>> game_data = { 'Player-position' : 'N23 E45', 'pockets' : ['keys', 'pocket knife', 'polished stone'], 'backpack' : ['rope', 'hammer', 'apple'], 'money' : 158.50 }
여기서 우리는 가상의 게임에 있는 플레이어의 현재 위치와 플레이어의 주머니 및 가방에 있는 항목 목록,
그리고 가지고 있는 돈에 대한 정보를 가진 파이썬 맵을 생성한다.
그리고 다음과 같이 이 맵을 파일로 저장하고 pickle의 dump 함수를 호출한다.
>>> import pickle >>> game_data = { 'Player-position' : 'N23 E45', 'pockets' : ['keys', 'pocket knife', 'polished stone'], 'backpack' : ['rope', 'hammer', 'apple'], 'money' : 158.50 } >>> save_file = open('save.dat', 'wb') >>> pickle.dump(game_data, save_file) >>> save_file.close()
pickle 모듈을 먼저 임포트하고
게임 데이터의 맵을 생성한다.
open 함수의 매개변수 wb로 save.dat 파일을 연다.
이것은 파이썬에게 이 파일을 바이너리 모드로 쓰라고 하는 것이다
맵과 파일 변수를 매개변수로 전달하기 위해서 dump를 사용한다.
마지막으로, 작업이 끝났으므로 그 파일을 닫는다.
/**********
일반 텍스트 파일(Plain text file)은 사람이 읽을 수 있는 문자들만 담는다.
이미지와 음악 파일, 영화, 피클된(pickled) 파이썬 객체들은 사람이 읽을 수 없는 정보를 가지고 있다.
그래서 그것들을 바이너리 파일이라고 한다.
만약 save.dat 파일을 열어본다면 텍스트 파일 같지 않은 것들이 보일 것이다.
이것은 정상적인 텍스트와 특수문자들이 섞인 것처럼 보일 것이다.
***********/
pickle의 load 함수를 사용하여 파일로 쓴 객체를 언피클(unpickle)할 수 있다.
언피클은 피클(pickle) 작업을 역으로 하는 것이다. 이것은 파일에 쓴 정보를 가져다가
프로그램이 사용할 수 있는 값으로 변환시킨다.
이 절차는 dump 함수를 사용하는 것과 비슷하다.
>>> load_file = open('save.dat', 'rb') >>> loaded_game_data = pickle.load(load_file) >>> load_file.close()
먼저 매개 변수로 rb(read binary라는 뜻)를 사용해 파일을 연다.
그런 다음 파일을 load 함수에 전달하고 반환값을 변수 loaded_game_data 에 설정한다.
마지막으로, 그 파일을 닫는다.
저장된 데이터가 올바르게 로드되었는지를 확인하기 위해 그 변수를 출력해본다.
>>> print(loaded_game_data) {'money': 158.5, 'pockets': ['keys', 'pocket knife', 'polished stone'], 'backpack': ['rope', 'hammer', 'apple'], 'Player-position': 'N23 E45'}
여기서는 파이썬 모듈이 함수와 클래스, 변수들을 어떻게 그룹화하는지 살펴봤고,
모듈을 임포트해 여러 함수들을 어떻게 사용하는지를 배웠다.
객체를 복사하는 방법과 난수를 만드는 방법, 객체들의 리스트를 무작위로 섞는 방법뿐만 아니라
파이썬에서 시간을 가지고 작업하는 방법도 살펴봤다.
마이막으로 pickle을 이용하여 정보를 저장하고 로드하는 방법을 배웠다.
'Python > Python 기초' 카테고리의 다른 글
구문 (Statement) (0) | 2014.12.07 |
---|---|
파이썬 버전 2와 버전 3의 차이점 (3) | 2014.12.06 |
파이썬의 유용한 내장 함수 (0) | 2014.10.30 |
클래스와 객체를 사용하는 방법 (0) | 2014.10.26 |
튜플 (Tuple) (0) | 2014.10.26 |