book.dvi
|
|
- 예인 현
- 8 years ago
- Views:
Transcription
1 정보교육을 위한파이썬 정보탐색을통한데이터과학자로의여정 Version d2 저자: Charles Severance 번역: 이광춘 (xwmooc)
2 Copyright Charles Severance.한국어번역 : 이광춘(xwMOOC) 출판 이력: 2014년 12월: 한국어색인,그림한글번역,목차한글반영,주요용어표준화 2014년 9월: xwmooc프로젝트 일환으로 정보과학을 위한파이썬 으로제목정하고 한국어로번역공개 2013년 10월: JSON로전환, OAuth사용. 13장, 14장에주요개정,신규시각화 장추가. 2013년 9월: Amazon CreateSpace책출판 2010년 1월 : 미시건 대학 Espresso Book Machine 사용 책 출판 2009년 12월: Think Python: How to Think Like a Computer Scientist에서 2장 ~ 10장까 지주요개정 Python for Informatics: Exploring Information을 위해 1장, 11장~15장저작 2008년 6월: Think Python: How to Think Like a Computer Scientist제목바꾸고,주요 개정. 2007년 8월: How to Think Like a (Python) Programmer제목바꾸고,주요개정. 2002년 4월: How to Think Like a Computer Scientist초판공개 이 책은 크리에이티브 커먼즈 라이선스 3.0 (Creative Commons Attribution- NonCommercial-Share Alike 3.0)으로 인가되었다. 라이선스의 자세한 사항은 creativecommons.org/licenses/by-nc-sa/3.0/에 기재되어 있다. 저작권 상세 부 록에서저자가생각하는상업적,비상업적 이용그리고라이센스면제를생각하는바를 확인할수있다. 이책의 Think Python: How to Think Like a Computer Scientist의 LATEX 소스는 이용가능하다.
3 한국어판 서면 첫 인터넷웹브라우저를만든마크앤더슨은소프트웨어가세상을먹고 있다 ("Software is eating the world")는 자극적인 표현으로 2011년 월스트리트 저널 에에세이를썼고,카네기멜론대학의 쟈넷 윙교수는 이론적사고(Theoretical Thinking), 실험적 사고(Experimental Thinking))와 더불어 정보적 사고(Computational Thinking)가 현재도 그렇지만 앞으로 인간의 사고를 지배하는 중추적인 역할을할것을주장했다. 이들의결과는정보적사고를배운사람과소프트웨 어를 이해하고활용하는사람과그렇지못한사람과의차이는산업경제의빈 부격차보다더큰디지털경제의정보불평등(Digital Divide)를야기할것으로 예측했다. 정부는 14년 7월세계경제,사회환경이소프트웨어중심사회로급격히변화 하고 있으며,소프트웨어가혁신과성장,가치창출의중심이되고,개인 기업 국가의경쟁력을좌우하는중요한역할을하고 있음에도불구하고,우리나라는 범정부적,국민적관심이미흡한상황이라고진단하고,미국,영국, 이스라엘등 선진국과마찬가지로,초 중 고에서소프트웨어를필수로 이수할수있는방안 을강구하고 있다. 하지만,지금까지의관심은소프트웨어만집중되어왔고,정보및데이터에대 한부분은상대적으로소홀히다뤄왔다. Python for Informatics 번역을통해서 컴퓨터언어를쉽고빠르게그리고정보및데이터에대한부분도효과적으로 학습할수있을것으로기대한다. 이광춘 (xwmooc) 서울종로세운상가 2014년 12월
4 iv 제 0 장. 한국어판서면
5 서면 정보교육을 위한 파이썬: 공개된 책 리믹싱 출판혹은소멸(publish or perish) 를들어온학자는 자신만의신선한창조로무 에서만들어내는것은무척이나 자연스럽다. 이책은아무것도없는것에서시 작하는 대신에 Allen B. Downey, Jeff Elkner와 협력자들이 저작한 Think Python: How to Think Like a Computer Scientist 책을 리믹싱(re-mixing) 하는 실험이다. 2009년 12월,미시건대학에서연속해서 5학기 SI502 - Networked Programming을준비중이었고,알고리즘과추상화를 이해하는대신에데이터탐색에집 중하는파이썬교과서를쓸시점이라고정했다. SI502목표는파이썬을사용하 여사람들에게평생데이터를다루는기술을가르치는것이다.대신에,핵생들 중누구도전문적인컴퓨터프로그래머를계획한사람은없었다.대신에학생 들은도서관원,관리자,변호사,생물학자,경제학자가되고자했는데 자신만의 영역에서능숙하게기술을사용하고자했다. 수업을 위해서결코완벽한데이터지향파이썬책을발견할것같지않아서그 런책을저작하려고시작했다.휴가기간동안아무것도없는상태에서새로운 책을시작하기 3주전다행스럽게도교수회의에서, Atul Prakash박사가지난 학기파이썬과정을가르치는데사용한 Think Python책을보여주었다.간결하 고직접적인설명에학습하기쉬운것에초점을맞춘 잘쓰여진컴퓨터과학 교과서였다. 전반적인책의구조는가능한빠르게데이터분석문제를다루고,처음부터데 이터분석에관한실전예제와연습문제로바꾸었다 장은 Think Python책과매우 유사하지만주요변경사항이 있다.숫자중 심의예제와연습문제는데이터지향연습으로대체했다.주제는순차적으로 제시되어서점차적으로정교한데이터분석솔류션을구축하도록했다. try,
6 vi 제 0 장. 서면 except같은주제는앞으로가져와서조건문 장의 일부에제시했다.함수는추 상화의첫수업에소개되기보다는프로그램복잡성을다루는데필요할때까지 매우가볍게다루었다.거의모든사용자정의함수는 4장밖으로예제코드와연 습문제를제거했다.단어 재귀(recursion) 1 는책의어디에도나타나지않는다. 1장, 11-16장의모든콘텐츠는완전히새로운실무사용과데이터분석을 위한 파이썬간단한예제에집중했다.데이터분석은검색과파싱를 위한정규표현 식,사용자컴퓨터의 작업 자동화,네트워크상에서데이터가져오기,데이터 로웹페이지스크랩핑,웹서비스사용하기, XML과 JSON데이터파싱,그리고 SQL(Structured Query Language)을 사용한 데이터베이스 생성 및 사용을 포함 한다. 이 모든 변화의 궁극적인 목적은 컴퓨터 과학에서 인포매틱스(informatics)로 전환이고,설사전문적인프로그래머가되지않을지라도 유용한첫기술과목 안으로 의제를포괄하는것이다. 이책이 흥미롭고 좀더 탐색하고자 하는 학생은 Allen B. Downey 의 Think Python책을봐야한다.두책간에많이겹치는부분이 있어서, Think Python에서 다루는기술적인프로그래밍과알고리즘적사고에대한기술을빠르게습득할 것이다.그리고,책의저작스타일매우 유사해서,최소의노력으로 Think Python 을통해서빠르게나아갈수있다. Think Python저작권자로서, Allen은 GNU공개문서라이센스가적용된본인 의책에서 이책에적용된좀더최근의크리에이티브커먼즈저작자명시,동일 한 라이선스 적용(CC-BY-SA)변경하도록 허가를 주었다. 공개 문서 라이센스가 GFDL에서 CC-BY-SA(예, 위키피디아) 바뀌는 추세를 따르는 것이다. CC-BY- SA라이선스를사용하는것은책에대한강력한카피레프트전통을 유지하면 서,새로운저자가 재사용해서 자신의목적에맞춰사용하도록좀더직접적으로 만드는것이다. 이책이왜공개저작물이미래교육에매우중요하다고느끼 고,책을공개저작권아래에서 이용가능하게만든앞을내다보는결정을내린 Allen B. Downey와 Cambridge University Press에 감사드린다. 저자 노력의 결 과에기뻐하고,독자는모두의공동노력에즐거워하길희망한다. 이책과관련된저작권 이슈를해결하고처리하는데 인내를가지고도움과안 내를 주신 Allen B. Downey와 Lauren Cowles 분께 감사를 표한다. Charles Severance 1 물론 이번줄은제외다.
7 vii Ann Arbor, MI, USA 2013년 9월 9일 Charles Severance는 미시건 대학 정보 학교 부교수다.
8 viii 제 0 장. 서면
9 차례 한국어판 서면 iii 서면 v 제 1 장 왜프로그래밍을배워야하는가? 1 제 1절 창의성과동기 제 2절 컴퓨터하드웨어아키텍처 제 3절 프로그래밍 이해하기 제 4절 단어와문장 제 5절 파이썬과대화하기 제 6절 전문용어: 인터프리터와컴파일러 제 7절 프로그램 작성하기 제 8절 프로그램이란무엇인가? 제 9절 프로그램구성요소 제 10절 프로그램이 잘못되면? 제 11절 학습으로의여정 제 12절 용어사전 제 13절 연습문제
10 x 차례 제 2 장 변수,표현식,문장(Statement) 19 제 1절 값(Value)과 자료형(Type) 제 2절 변수(Variable) 제 3절 변수명(Variable name)과예약어(keywords) 제 4절 문장(Statement) 제 5절 연산자(Operator)와피연산자(Operands) 제 6절 표현식(Expression) 제 7절 연산자적용우선순위 (Order of Operations) 제 8절 나머지연산자 (Modulus Operator) 제 9절 문자열연산자 (String Operator) 제 10절 사용자에게서 입력값받기 제 11절 주석 제 12절 연상되는변수명만들기 제 13절 디버깅(Debugging) 제 14절 용어설명 제 15절 연습문제 제 3 장 조건부실행 31 제 1절 불표현식(Boolean expressions) 제 2절 논리연산자 제 3절 조건문실행 제 4절 대안실행 제 5절 연쇄조건문 제 6절 중첩조건문 제 7절 try와 catch를활용한예외처리
11 차례 xi 제 8절 논리연산식의단락(Short circuit)평가 제 9절 디버깅(Debugging) 제 10절 용어정의 제 11절 연습문제 제 4 장 함수 43 제 1절 함수호출 제 2절 내장(Built-in)함수 제 3절 자료형(type)변환함수 제 4절 난수(Random numbers) 제 5절 수학함수 제 6절 신규함수추가 제 7절 함수정의와사용법 제 8절 실행흐름 제 9절 매개변수(parameter)와 인수(argument) 제 10 절 결과있는 함수(fruitful function)와 빈 함수(void function).. 50 제 11절 왜함수를사용하는가? 제 12절 디버깅 제 13절 용어정의 제 14절 연습문제 제 5 장 반복(Iteration) 57 제 1절 변수갱신 제 2절 while문 제 3절 무한루프 제 4절 무한반복과break
12 xii 차례 제 5절 continue로반복종료 제 6절 for문을사용한명확한루프 제 7절 루프패턴 제 8절 디버깅 제 9절 용어정의 제 10절 연습문제 제 6 장 문자열 67 제 1절 문자열은순서(sequence)다 제 2절 len함수사용문자열길이구하기 제 3절 루프를사용한문자열운행법 제 4절 문자열슬라이스(slice) 제 5절 문자열은불변이다 제 6절 루프돌기(looping)계수(counting) 제 7절 in연산자 제 8절 문자열비교 제 9절 string메쏘드 제 10절 문자열파싱(Parsing) 제 11절 서식연산자 제 12절 디버깅 제 13절 용어정의 제 14절 연습문제
13 차례 xiii 제 7 장 파일 79 제 1절 영속성(Persistence) 제 2절 파일열기 제 3절 텍스트파일과라인 제 4절 파일 읽어오기 제 5절 파일검색 제 6절 사용자가파일명을선택하게만들기 제 7절 try, except, open사용하기 제 8절 파일에쓰기 제 9절 디버깅 제 10절 용어정의 제 11절 연습문제 제 8 장 리스트 (List) 91 제 1절 리스트는순서(sequence)다 제 2절 리스트는변경가능하다 제 3절 리스트운행법 제 4절 리스트연산자 제 5절 리스트슬라이스(List slices) 제 6절 리스트메쏘드 제 7절 요소삭제 제 8절 리스트와함수 제 9절 리스트와문자열 제 10절 라인파싱하기(Parsing) 제 11절 객체와값(value)
14 xiv 차례 제 12절 에일리어싱(Aliasing) 제 13절 리스트 인수 제 14절 디버깅 제 15절 용어정의 제 16절 연습문제 제 9 장 딕셔너리(Dictionaries) 107 제 1절 계수기(counter)집합으로서딕셔너리 제 2절 딕셔너리와파일 제 3절 반복과딕셔너리 제 4절 고급텍스트파싱 제 5절 디버깅 제 6절 용어정의 제 7절 연습문제 제 10 장 튜플(Tuples) 117 제 1절 튜플은불변이다 제 2절 튜플비교하기 제 3절 튜플대입(Tuple Assignment) 제 4절 딕셔너리와튜플 제 5절 딕셔너리로다중대입 제 6절 가장빈도수가높은단어 제 7절 딕셔너리키로튜플사용하기 제 8절 순서(sequence) :문자열,리스트,튜플 제 9절 디버깅 제 10절 용어정의 제 11절 연습문제
15 차례 xv 제 11 장 정규 표현식 129 제 1절 정규표현식의문자매칭 제 2절 정규표현식사용데이터추출 제 3절 검색과추출조합하기 제 4절 이스케이프(Escape)문자 제 5절 요약 제 6절 유닉스사용자를 위한보너스 제 7절 디버깅 제 8절 용어정의 제 9절 연습문제 제 12 장 네트워크 프로그램 141 제 1 절 하이퍼 텍스트 전송 프로토콜(HyperText Transport Protocol - HTTP) 제 2절 세상에서가장간단한웹브라우져(Web Browser) 제 3절 HTTP를통해서 이미지가져오기 제 4절 urllib사용하여웹페이지가져오기 제 5절 HTML파싱과웹스크래핑 제 6절 정규표현식사용 HTML파싱하기 제 7절 BeautifulSoup사용한 HTML파싱 제 8절 urllib을사용하여바이너리파일 읽기 제 9절 용어정의 제 10절 연습문제
16 xvi 차례 제 13 장 웹서비스 사용하기 153 제 1절 XML(eXtensible Markup Language) 제 2절 XML파싱 제 3절 노드반복하기 제 4절 JSON(JavaScript Object Notation) 제 5절 JSON파싱하기 제 6 절 API(Application Program Interfaces, 응용 프로그램 인터페 이스) 제 7 절 구글 지오코딩 웹서비스(Google Geocoding Web Service) 제 8절 보안과 API사용 제 9절 용어정의 제 10절 Exercises 제 14 장 데이터베이스와 SQL(Structured Query Language)사용하기 167 제 1절 데이터베이스가뭔가요? 제 2절 데이터베이스개념 제 3절 파이어폭스애드온 SQLite매니저 제 4절 데이터베이스테이블생성하기 제 5절 SQL(Structured Query Language)요약 제 6 절 데이터베이스를 사용한 트위터 스파이더링(Spidering) 제 7절 데이터모델링기초 제 8절 다중테이블을가지고프로그래밍 제 9절 세종류의키 제 10절 JOIN을사용하여데이터가져오기 제 11절 요약 제 12절 디버깅 제 13절 용어정의
17 차례 xvii 제 15 장 데이터 시각화 189 제 1절 지리정보데이터로구글맵생성하기 제 2절 네트워크와상호연결시각화 제 3절 전자우편데이터시각화 제 16 장 컴퓨터의 일반적인 작업 자동화 199 제 1절 파일 이름과경로 제 2절 예제:사진디렉토리정리하기 제 3절 명령줄인자 제 4절 파이프(Pipes) 제 5절 용어정의 제 6절 연습문제 부록 A 윈도우상에서파이썬프로그래밍 209 부록 B 매킨토쉬 상에서 파이썬 프로그래밍 211 부록 C 공헌(contribution) 213 부록 D 저작권 세부정보 217
18 xviii 차례
19 제 1 장 왜 프로그래밍을 배워야 하는가? 컴퓨터프로그램을만드는행위(프로그래밍)는매우창의적이며향후뿌린것 이상으로얻을것이많다.프로그램을만드는 이유는어려운 자료분석문제를 해결하려는것에서부터다른사람의문제를해결해주는데 재미를느끼는것까 지다양한 이유가 있다. 이책을통해서모든사람 이어떻게프로그램을만드는 지를알고,프로그램이어떻게만드는지를알게되면,새로습득한프로그래밍 기술로하고자하는것을해결할수있게된다. 우리의 일상은노트북에서부터스마트폰까지다양한종류의컴퓨터에둘러싸 여 있다. 이러한컴퓨터를우리를 위해서많은 일을대신해주는 "개인비서"로 생각한다. 일상생활에서접하는컴퓨터하드웨어는우리에게 "다음에무엇을 하면 좋겠습니까?" 라는 질문을 지속적으로 던지게 만들어 졌다. 다음에 무엇을 할까요? 다음에 무엇을 할까요? 다음에 무엇을 할까요? 다음에 무엇을 할까요? 다음에 무엇을 할까요? 다음에 무엇을 할까요? 개인 휴대 정보 단말 (PDA) 프로그래머는운영체제와하드웨어에 응용프로그램을추가했고,결국많은 것들을 도와주는 개인 휴대 정보 단말(Persoanl Digital Assistant, PDA)로 진화 했다. 사용자여러분이컴퓨터에게 "다음실행해 (do next)"를컴퓨터가 이해할수있 는언어로지시를할수만 있다면,컴퓨터는빠르고,저장소가커서,매우 유용 하게사용될수있다.만약컴퓨터언어를알고 있다면,반복적인 작업을사람을 대신해서컴퓨터에지시할수있다.흥미롭게도,컴퓨터가가장 잘할수있는종
20 2 제 1 장. 왜프로그래밍을배워야하는가? 류의 작업들은종종사람들이 재미없고,너무나지루하다고생각하는것이다. 예를들어, 이번 장의첫세문단을보고,가장많이나오는단어를찾아보고얼 마나 자주나오는지를알려주세요.사람이몇초내에단어를 읽고 이해할수는 있지만,그단어가몇번나오는지세는것은매우고생스러운 작업이다.왜냐하 면사람이지루하고반복되는문제를해결하는데적합하지않기때문이다.컴 퓨터는 정반대이다. 논문이나 책에서 텍스트를 읽고 이해하는 것은 컴퓨터에게 어렵다.하지만,단어를세고가장많이사용되는단어를찾는것은컴퓨터에게 는무척이나쉬운 작업이다. python words.py Enter file:words.txt to 16 우리의개인정보분석도우미는 이번장의첫세문단에서단어 "to"가가장많이 사용되었고, 16번 나왔다고 바로 답을 준다. 사람이 잘하지못하는점을컴퓨터가 잘할수있다는사실을 이해하면왜"컴 퓨터언어"로컴퓨터와대화해야하는데능숙해야하는지알수있다.컴퓨터와 대화할수있는새로운언어(Python)를배우게되면,지루하고반복되는 일을컴 퓨터가처리하고,사람에게적합한 일을하는데더많은시간을할애할수있다. 그래서,여러분은직관,창의성,창의력을컴퓨터파트너와함께추진할수있다. 제 1절 창의성과동기 이책은직업으로프로그래밍을하는사람을 위해서저작된것은아니지만,직업 적으로프로그램을만드는 작업은개인적으로나경제적인면에서꽤매력적인 일이다.특히, 유용하며,심미적이고,똑똑한프로그램을다른사람이사용할수 있도록만드는것은매우창의적인활동이다.다양한그룹의프로그래머들이 사용자의 관심과 시선을 차지하기 위해서 경쟁적으로 작성한 다양한 종류의 프 로그램이 여러분의 컴퓨터와 개인 휴대 정보 단말기(Personal Digital Assistant, PDA)에담겨있다. 이렇게개발된프로그램은사용자가원하는바를충족시키 고훌륭한사용자경험을제공하려고노력한다.몇몇상황에서사용자가소프 트웨어를골라구매하게될때,고객의선택에대해프로그래머는바로경제적 보상을받게된다. 만약프로그램을프로그래머집단의창의적인결과물로생각해본다면,아마도 다음그림이좀더 의미 있는 PDA컴퓨터로보일것이다. 다음에 무엇을 할까요? 다음에 무엇을 할까요? 다음에 무엇을 할까요? 다음에 무엇을 할까요? 다음에 무엇을 할까요? 다음에 무엇을 할까요? 개인휴대 정보단말 (PDA)
21 2. 컴퓨터 하드웨어 아키텍처 3 우선은프로그래을만드는주된동기가사업을한다던가사용자를기쁘게한 다기보다, 일상생활에서맞닥뜨리는 자료와정보를 잘다뤄좀더생산적으로 우리의삶을만드는데초점을 잡아본다.프로그램을만들기시작할때,여러분 모두는 프로그래머이면서 동시에 자신이 만든 프로그램의 사용자가 된다. 프로 그래머로서기술을습득하고프로그래밍 자체가좀더창의적으로느껴진다면, 여러분은 다른 사람을 위해 프로그램을 개발하게 준비가 된 것이다. 제 2절 컴퓨터하드웨어아키텍처 소프트웨어개발을 위해컴퓨터에지시명령어를전달하기 위한컴퓨터언어를 학습하기전에,컴퓨터가어떻게구성되어 있는지 이해할필요가 있다.컴퓨터 혹은핸드폰을분해해서안쪽을살펴보면,다음과같은주요부품을확인할수 있다. 다음에 무엇을 실행할까? 입출력 장치 중앙처리 장치 네트워크 주기억장치 보조 기억장치 주요부품의상위수준정의는다음과같다. 중앙처리장치(Central Processing Unit, CPU): 다음 무엇을 할까요? ("What is next?")명령어를처리하는컴퓨터의주요부분이다.만약컴 퓨터중앙처리장치가 3.0 GHz라면,초당명령어 (다음무엇을할까요? What is next?)를삼백만번처리할수있다는것이다. CPU처리속도를따 라서빠르게컴퓨터와어떻게대화하는지학습할것이다. 주기억장치(Main Memory): 주기억장치는 중앙처리장치(CPU)가 급하 게명령어를처리하기하는데필요한정보를저장하는용도로사용된다. 주기억장치는 중앙처리장치만큼이나 빠르다. 그러나 주기억장치에 저장 된정보는컴퓨터가꺼지면 자동으로지워진다. 보조 기억장치(Secondary Memory): 정보를 저장하기 위해 사용되지만, 주기억장치보다속도는느리다.전기가나갔을때도정보를기억하는것 은 장점이다. 휴대용 USB나 휴대용 MP3 플레이어에 사용되는 USB 플래 쉬메모리나디스크드라이브가여기에속한다.
22 4 제 1 장. 왜프로그래밍을배워야하는가? 입출력장치(Input Output Devices): 간단하게 화면, 키보드, 마우스, 마 이크,스피커,터치패드가포함된다.컴퓨터와사람이상호작용하는모든 방식이포함된다. 네트워크(Network):요즘거의모든컴퓨터는네트워크로정보를주고 받는 네트워크 연결(Network Connection) 하드웨어가 있다. 네트워크는 항상 "이용가능"하지않을지도모르는데이터를저장하고가져오는매우 느린저장소로볼수있다.그러한점에서네트워크는좀더느리고,때때로 신뢰성이 떨어지는 보조 기억장치(Secondary Memory)의 한 형태로 볼 수 있다. 주요부품들이어떻게 작동하는지에대한세세한사항은컴퓨터제조자에게 맡겨져 있지만,프로그램을 작성할때컴퓨터주요부품에대해서언급되어서, 컴퓨터 전문용어를 습득하고 이해하는 것은 도움이 된다. 프로그래머로서 임무는 자료를분석하고문제를해결하도록,컴퓨터 자원각각 을 사용하고 조율하는 것이다. 프로그래머로서 대체로 CPU와 대화 해서 다음 무엇을실행하라고지시한다.때때로 CPU에주기억장치,보조기억장치,네트 워크,혹은 입출력장치도사용하라고지시한다. 다음에 무엇을 처리하지? 입출력 장치 중앙처리 장치 네트워크 주기억장치 여러분 보조기억 장치 프로그래머는컴퓨터의 "다음무엇을수행할까요?"에대한답을하는사람이기 도하다.하지만,컴퓨터에답하기 위해서 5mm크기로프로그래머를컴퓨터에 집어넣고초당 30억개명령어로답을하게만드는것은매우불편하다.그래서, 대신에미리컴퓨터에게수행할명령문을 작성해야한다. 이렇게미리 작성된 명령문 집합을 프로그램(Program)이라고 하며, 명령어 집합을 작성하고 명령 어집합이올바르게 작성될수있도록하는행위를프로그래밍(Programming) 이라고 부른다. 제 3절 프로그래밍 이해하기 책의나머지 장을통해서책을 읽고 있는여러분을프로그래밍 장인으로 인도할 것이다.종국에는책을 읽고 있는여러분모두프로그래머가될것이다.아마
23 4. 단어와 문장 5 도전문적인프로그래머는아닐지라도적어도 자료/정보분석문제를보고그 문제를해결할수있는기술을가지게는될것이다. 이런점에서프로그래머가되기 위해서두가지기술이필요하다. 첫째,파이썬같은프로그래밍언어 -어휘와문법을알필요가 있다.단어 를새로운언어에맞추어 작성할수있어야하며새로운언어로 잘표현된 "문장"으로 어떻게 작성하는지도 알아야 한다. 둘째,스토리(Story)를말할수있어야한다.스토리를 작성할때,독자에 게아이디어(idea)를전달하기 위해서단어와문장을조합합니다.스토리 를구성할때기술적인면과예술적인면이 있는데,기술적인면은쓰기 연습을반복하고,피트백을받아향상된다.프로그래밍에서,우리가 작성 하는프로그램은 "스토리"가되고,해결하려고하는문제는 "아이디어"에 해당된다. 파이썬과같은프로그래밍언어를배우게되면, 자바스크립트나 C++같은두 번째언어를배우는것은무척이나쉽다.새로운프로그래밍언어는매우다른 어휘와문법을갖지만,문제를해결하는기술을배우면,다른모든프로그래밍 언어를통해서동일하게접근할수있습니다. 파이썬어휘와문장은매우빠르게학습할수있다.새로운종류의문제를풀기 위해논리적인프로그램을 작성하는것은더오래걸린다.여러분은 작문을배우 듯이프로그래밍을배우게된다.프로그래밍을 읽고설명하는것으로시작해서, 간단한프로그램을 작성하고,점차적으로복잡한프로그램을 작성할것이다.어 느순간에명상에 잠기게되고,스스로패턴이눈에들어오게된다.그러면,좀더 자연스럽게문제를어떻게받아들이고,그문제를해결할수있는프로그램을 작성하게된다.마지막으로,그순간에도착하게되면,프로그래밍은매우즐겁 고창의적인과정이된다. 파이썬프로그램의어휘와구조로시작한다.간단한예제가처음으로언제프 로그램을 읽기 시작했는지를 상기시켜주니 인내심을 가지세요. 제 4절 단어와문장 사람언어와달리,파이썬어휘는사실매우적다.파이썬어휘를예약어(researved words)로부른다. 이들단어는파이썬에매우특별한 의미를부여한다. 파이썬프로그램관점에서파이썬이 이들단어를보게되면,파이썬에게는단 하나의 유일한 의미를갖는다.나중에여러분들이프로그램을 작성할때, 자신 만의단어를 작성하는데 이를변수(Variable)라고한다.변수 이름을지을때 폭넓은 자유를갖지만,변수 이름으로파이썬예약어를사용할수는없다. 이런점에서강아지를훈련시킬때"걸어(walk)", "앉아", "기달려", "가져와" 같은특별한어휘를사용한다.강아지에게 이와같은특별한예약어를사용하 지않을때는,주인이특별한어휘를사용할때까지강아지는주인을물끄러미 쳐다보기만한다.예를들어, "더많은사람들의건강을전반적으로향상하는
24 6 제 1 장. 왜프로그래밍을배워야하는가? 방향으로동참하여 "걷기(walk)"를원한다"고말하면,강아지가듣는것은 뭐 라뭐라뭐라 걷기(walk)뭐라 와같이들릴것이다.왜냐하면 "걸어(walk)"가 강아지언어에는예약어 1 이기때문이다. 이러한사실이아마도개와고양이사 이에는어떠한예약어도존재하지않는다는것을 의미할지모른다. 사람이파이썬과대화하는언어예약어는다음과같다. and del from not while as elif global or with assert else if pass yield break except import print class exec in raise continue finally is return def for lambda try 강아지사례와사뭇다르게파이썬은 이미완벽하게훈련이되어 있다.여러 분이 "try"라고말하면,매번 "try"라고말할때마다실패없이파이썬은항시 시도한다. 상기예약어를학습하고,어떻게 잘사용되는지도함께학습할것이지만,지금 은파이썬에말하는것에집중할것이다.파이썬과대화하는것중좋은점은 다음과같이 인용부호로감싸메세지를던지는것만으로도파이썬에말을할수 있다는 것이다. print 'Hello world!' 상기간단한문장은파이썬구문(Syntax)론적으로도완벽하다.상기문장은예 약어 print 로시작해서출력하고자하는문자열을 작은따옴표로감싸서올바 르게 파이썬에게 전달했다. 제 5절 파이썬과대화하기 파이썬으로우리가알고 있는단어를가지고간단한문장을만들었으니 이제부 터는새로운언어기술을시험하기 위해서파이썬과대화를어떻게시작하는지 알필요가 있다. 파이썬과대화를시작하기전에,파이썬소프트웨어를컴퓨터에설치하고파이 썬을 컴퓨터에서 어떻게 실행하는지를 학습해야 한다. 이번 장에서 다루기에는 너무 구체적이고 자세한 사항이기 때문에 참조하는 것을권한다. 윈도우와매킨토쉬시스템상에서설치하고실행하는방법을 자세 한 설치절차와 함께 화면을 캡쳐하여 설명하였다. 설치가 마무리되고 터미널이 나 윈도우명령어실행창에서 python을타이핑하게되면,파이썬 인터프리터가 인터랙티브 모드로 실행을 시작하고 다음과 같은 것이 화면에 뿌려진다. Python (r261:67515, Jun , 21:47:49) [GCC (Apple Inc. build 5646)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> 1
25 5. 파이썬과대화하기 7 파이썬 인터프리터는»>프롬프트를통해서여러분에게요청사항("다음에파 이썬이무엇을실행하기를원합니까?")을접수받는방식을취한다.파이썬은 여러분과대화를나눌준비가되었다. 이제남은것은파이썬언어로어떻게 말하고어떻게파이썬과대화하는지아는것이다. 예를들어,여러분이가장간단한파이썬언어단어나문장조차도알수가없다 고가정하자.우주비행사가저멀리떨어진행성에착륙해서행성의거주민과 대화를시도할때사용하는간단한말을사용해보자. >>> I come in peace, please take me to your leader File "<stdin>", line 1 I come in peace, please take me to your leader ^ SyntaxError: invalid syntax >>> 잘되는것같지않다.뭔가빨리다른생각을내지않는다면,행성거주민은여 러분을창으로찌르고,침으로바르고,불위 잘구워바베큐로만들어저녁으로 먹을듯하다. 운좋게도기나긴우주여행중이책의복사본을가지고와서다음과같이빠르 게 타이핑한다고 생각하자. >>> print 'Hello world!' Hello world! 훨씬 좋아보인다. 이제 좀더 커뮤니케이션을 이어갈 수 있을 것으로 보인다. >>> print 'You must be the legendary god that comes from the sky' You must be the legendary god that comes from the sky >>> print 'We have been waiting for you for a long time' We have been waiting for you for a long time >>> print 'Our legend says you will be very tasty with mustard' Our legend says you will be very tasty with mustard >>> print 'We will have a feast tonight unless you say File "<stdin>", line 1 print 'We will have a feast tonight unless you say ^ SyntaxError: EOL while scanning string literal >>> 이번대화는 잠시동안 잘진행되다가여러분이파이썬언어로말하는데정말 사소한 실수를 저질러 파이썬이 다시 창을 여러분에게 겨눈다. 이시점에파이썬은놀랍도록복잡하고강력하며파이썬과 의사소통을할때사 용하는구문(syntax)은매우까다롭다는것은알수있다.파이썬은다른말로안 똑똑(Intelligent)하다. 지금까지 여러분은 자신과 대화를 적절한 구문(syntax)을 사용해서 대화했다. 여러분이다른사람이 작성한프로그램을사용한다는것은파이썬을사용하는 다른프로그래머가파이썬을중간매개체로사용하여대화한것으로볼수있 다. 프로그램을 만든 저작자가 대화가 어떻게 진행되어져야 하는지를 표현하는
26 8 제 1 장. 왜프로그래밍을배워야하는가? 방식이파이썬이다.다음몇장에걸쳐서다른많은프로그래머중의한명처럼, 파이썬으로 여러분이 작성한 프로그램을 이용하는 사용자와 대화하게 된다. 파이썬 인터프리터와첫번째대화를끝내기전에,파이썬행성의거주자에게 " 안녕히계세요"를말하는적절한방법도알아야한다. >>> good-bye Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'good' is not defined >>> if you don't mind, I need to leave File "<stdin>", line 1 if you don't mind, I need to leave ^ SyntaxError: invalid syntax >>> quit() 상기처음두개시도는다른오류메세지를출력한다.두번째오류는다른데 이유는 if가예약어이기때문에파이썬은 이예약어를보고뭔가다른것을말한 다고 생각하지만, 잠시 후 구문이 잘못됐다고 판정하고 오류를 뱉어낸다. 파이썬에 "안녕히계세요"를말하는올바른방식은 인터렉티브»>프롬프트에 서 quit()를 입력하는 것이다. 제 6절 전문용어: 인터프리터와 컴파일러 파이썬은상대적으로직접사람이 읽고쓸수도 있고,컴퓨터도 읽고처리할수 있도록고안된하이레벨(High-level)언어이다.다른하이레벨언어에는 자바, C++, PHP,루비,베이직,펄, 자바스크립트등다수가포함되어 있다.실제하드 웨어 중앙처리장치(CPU)내에서는 하이레벨 언어를 조금도 이해하지 못한다. 중앙처리장치는 우리가 기계어(machine-language)로 부르는 언어만 이해한다. 기계어는매우간단하고솔직히 작성하기에는매우귀찮다.왜냐하면모두 0과 1로만 표현되기 때문이다 표면적으로 0과 1로만되어 있기때문에기계어가간단해보이지만,구문은매 우복잡하고파이썬보다훨씬어렵다.그래서매우소수의프로그래머만이기 계어로 작성할수있다.대신에,프로그래머가파이썬과 자바스크립트같은하 이레벨언어로 작성할수있게다양한번역기(translator)를만들었다. 이러한 번역기는프로그램을중앙처리장치에 의해서실제실행이가능한기계어로변 환한다. 기계어는특정컴퓨터하드웨어에묶여있기때문에기계어는다른형식의하 드웨어에는 이식(portable)되지 않는다. 하이 레벨 언어로 작성된 프로그램은
27 6. 전문용어: 인터프리터와 컴파일러 9 두가지방식으로 이기종의컴퓨터로 이식이가능하다.한방법은새로운하 드웨어에 맞게 기계어를 재컴파일(recompile)하는 것이고, 다른 방법은 새로운 하드웨어에맞는다른 인터프리터를 이용하는것이다. 프로그래밍언어번역기는 일반적으로두가지범주가 있다. (1) 인터프리터 (2) 컴파일러 인터프리터는프로그래머가코드를 작성할때소스코드를 읽고,소스코드를 파싱하고,즉석에서명령을해석한다.파이썬은 인터프리터다.따라서,파이썬 을 인터렉트브모드로실행할때,파이썬명령문(한문장)을 작성하면,파이썬이 즉석에서처리하고,사용자가다른파이썬명령어를 입력하도록준비를한다. 파이썬코드의 일부는나중에사용될것이니파이썬에게기억하도록명령한다. 적당한 이름을골라서값을기억시키고,나중에그이름을호출하여값을사용 한다. 이러한목적으로저장된값을참조하는목적으로사용되는표식(label)을 변수(variable)라고 한다. >>> x = 6 >>> print x 6 >>> y = x * 7 >>> print y 42 >>> 상기예제에서파이썬이값6을기억하고 있다가,라벨 x를사용하여나중에 값을가져오게만들었다. print예약어를사용하여파이썬이 잘기억하고 있는 지를검증한다.그리고 x를가져와서 7을곱하고새로운변수 y에값을집어 넣는다.그리고 y에현재무슨값이저장되었는지출력하라고파이썬에게지시 한다. 한줄한줄파이썬에명령어를 입력하고 있지만,앞쪽명령문에서생성된 자료가 뒤쪽실행명령문에서사용될수있도록파이썬은순차적으로정렬된문장으로 처리한다.방금전논리적이고 의미있는순서로 4줄명령문을간단하게한단락 으로 작성했다. 위에서본것처럼파이썬과 인터랙티브하게대화를주고받는것이 인터프리터 의본질이다. 컴파일러가동작하기 위해서는먼저완전한프로그램을파일하나 에담고,하이레벨소스코드를기계어로번역하는과정을거치고,마지막으로 나중에실행되도록변환된기계어를파일에담는다. 윈도우를 사용한다면, 실행가능한 기계어 프로그램 확장자가 ".exe"(executable), 혹은 ".dll"(dynamically loadable library)임을 확인할 수 있다. 리눅스와 매킨토쉬에는 실행파일을 의미하는 특정 확장자는 없다. 텍스트편집기에서실행파일을열게되면,다음과같이 읽을수없는좀괴상한 출력결과를 화면상에서 확인한다. ^?ELF^A^A^A^@^@^@^@^@^@^@^@^@^B^@^C^@^A^@^@^@\xa0\x82 ^D^H4^@^@^@\x90^]^@^@^@^@^@^@4^@ ^@^G^@(^@$^@!^@^F^@ ^@^@4^@^@^@4\x80^D^H4\x80^D^H\xe0^@^@^@\xe0^@^@^@^E
28 10 제 1 장. 왜프로그래밍을배워야하는가? ^@^@^@^D^@^@^@^C^@^@^@^T^A^@^@^T\x81^D^H^T\x81^D^H^S ^@^@^@^S^@^@^@^D^@^@^@^A^@^@^@^A\^D^HQVhT\x83^D^H\xe8... 기계어를 읽고쓰는것은쉽지않다.그래서 C나파이썬같은하이레벨언어로 작성된프로그램을기계어로 자동번역해주는 인터프리터와 컴파일러가 있다 는것은멋진 일이다. 컴파일러와, 인터프리터를논의하는 이시점에,파이썬 인터프리터 자체에대 해서약간궁금해야한다.무슨언어로 작성되었을까?컴파일된언어로 작성되 었을까? python 을타이핑하게될때,정확하게무슨 일이 일어나는걸까? 파이썬 인터프리터는하이레벨언어 C 로 작성되었다.파이썬 인터프리터실 제소스코드를보려면, 개발할수있는소스코드를확인할수있다.그래서,파이썬그자체는프로그램 이다.기계어로컴파일되어 있어서파이썬을여러분의컴퓨터에설치(혹은컴 퓨터제조자가설치를대신해주기도함)한다는것은번역된파이썬프로그램 기계어코드사본을여러분컴퓨터에복사하는것에불과하다. 윈도우시스템 에서파이썬실행가능한기계어코드는파일에다음과같은 이름을갖는다. C:\Python27\python.exe 지금까지살펴본것은파이썬프로그래머가되기 위해서정말알필요가 있는것 이상이다.하지만,때때로처음에 이런귀찮은질문에바로답하는것이나중에 보상을한다. 제 7절 프로그램 작성하기 파이썬 인터프리터에명령어를타이핑하는것은파이썬주요기능을알아보는 좋은 방법이지만, 좀더 복잡한 문제를 해결하는데 권하지는 않는다. 프로그램을 작성할때,텍스트편집기를사용해서스크립트(script)로불리는파 일에 명령어 집합을 작성한다. 관례로, 파이썬 스크립트 확장자는.py가 된다. 스크립트를실행하기 위해서,파이썬 인터프리터에파일 이름을넘겨준다. 유 니스나 윈도우명령창에서 python hello.py를 입력하게되면다음과같은결 과를 얻는다. csev$ cat hello.py print 'Hello world!' csev$ python hello.py Hello world! csev$ csev$ 은 운영시스템 명령어 프롬프트이고, cat hello.py 는 문자열을 출력하 는한줄파이썬프로그램을담고 있는 hello.py 파일을화면에출력하라는명 령어입니다. 인터랙트브모드에서파이썬코드 입력하는방식대신에파이썬 인터프리터를 호출해서 hello.py 파일로부터 소스코드를 읽도록 지시합니다.
29 8. 프로그램이란 무엇인가? 11 이새로운방식은파이썬프로그램을끝마치기 위해 quit()를사용할필요가없 다는점에서편리합니다.파일에서소스코드를 읽을때,파일끝까지 읽게되면 자동으로파이썬이종료됩니다. 제 8절 프로그램이란무엇인가? 프로그램(Program)의가장본질적인정의는특정 작업을수행할수있도록조 작된 일련의파이썬문장의집합이다.가장간단한 hello.py스크립트도프로그 램이다.한줄의프로그램이특별히 유익하고쓸모가 있는것은아니지만엄격한 의미에서 파이썬 프로그램이 맞다. 프로그램을 이해하는가장쉬운방법은프로그램이해결하려고만들어진문제 를먼저생각해보고나서,그문제를풀어가는프로그램을살펴보는것이다. 예를들어,페이스북에게시된 일련의글에서가장 자주사용된단어에관심을 가지고소셜컴퓨팅연구를한다고생각해봅시다.페이스북에게시된글들을 쭉출력해서가장흔한단어를찾으려고열심히들여다볼것이지만,매우오래 걸리고실수하기도쉽다.하지만파이썬프로그램을 작성해서빨리정확하게 작업을 마무리한다면 똑똑하게 주말을 재미나게 보낼 수 있다. 예를들어 자동차(car)와광대(clown)에관한다음텍스트에서,가장많이나오 는단어가무엇이며몇번나왔는지세어보세요. the clown ran after the car and the car ran into the tent and the tent fell down on the clown and the car 그리고나서,몇백만줄의텍스트를보고서동일한 일을한다고상상해보자.솔 직히수작업으로단어를세는것보다파이썬을배워프로그램을 작성하는것이 훨씬빠를것이다. 더좋은소식은 이미텍스트파일에서가장 자주나오는단어를찾아내는간단 한프로그램을개발했다.저자가직접 작성했고,시험까지했다.바로사용을할 수 있도록준비했기때문에여러분의수고도덜수있다. name = raw_input('enter file:') handle = open(name, 'r') text = handle.read() words = text.split() counts = dict() for word in words: counts[word] = counts.get(word,0) + 1 bigcount = None bigword = None for word,count in counts.items(): if bigcount is None or count > bigcount: bigword = word bigcount = count print bigword, bigcount
30 12 제 1 장. 왜프로그래밍을배워야하는가? 상기프로그램을사용하려고파이썬을공부할필요도없다. 10장에걸쳐서멋진 파이썬프로그램을만드는방법을배우게될것이다.지금여러분은단순사용 자로서단순히상기프로그램을사용하게되면,프로그램의영리함과동시에얼 마나많은수작업노력을줄일수있는지감탄할것이다.단순하게코드를타이 핑해서 words.py파일로저장하고실행을하거나, com/code/에서 소스 코드를 다운받아 실행하면 된다. 파이썬과 파이썬 언어가 어떻게 여러분(사용자)과 저자(프로그래머)사이에서 중개자역할을훌륭히수행하고 있는지를보여주는좋은사례다.컴퓨터에파 이썬을설치한누구나사용할수있는공통의언어로 유용한명령순서(즉,프로 그램)를우리가주고받을수있는방식이파이썬이다.그래서누구도파이썬과 직접 의사소통하지 않고 파이썬을 통해서 서로 의사소통한다. 제 9절 프로그램구성요소 다음 몇장에 걸쳐서 파이썬 어휘, 문장구조, 문단구조, 스토리 구조에 대해서 학 습할것이다.파이썬의강력한역량에대해서배울것이고, 유용한프로그램을 작성하기 위해서 파이썬의 역량을 어떻게 조합할지도 학습할 것이다. 프로그램을 작성하기 위해서 사용하는 개념적인 하위 레벨(low-level) 패턴이 몇가지 있다.파이썬프로그램을 위해서만들어졌다기보다는기계어부터하 이 레벨(high-level) 언어에 이르기까지 모든 언어에도 공통된 사항이기도 하다. 입력: 컴퓨터바깥세계에서데이터를가져온다.파일로부터데이터를 읽을수 도 있고,마이크나 GPS같은센서에서데이터를 입력받을수도 있다.상기 초기프로그램에서 입력값은키보드를사용하여사용자가데이터를 입력 한것이다. 출력: 화면에 프로그램 결과값을 출력주거나 파일에 저장한다. 혹은 음악을 연 주하거나텍스트를 읽어스피커같은 장치에데이터를내보낸다. 순차실행: 스크립트에 작성된순서에맞춰한줄한줄실행된다. 조건실행: 조건을확인하고명령문을실행하거나건너뛴다. 반복실행: 반복적으로명령문을실행한다.대체로반복실행시변화를수반 한다. 재사용: 한벌의 명령문을 작성하여 이름을 부여하고 저장한다. 필요에 따라 프 로그램 이름을 불러 몇번이고 재사용한다. 너무나간단하게들리지만,전혀간단하지는않다.단순히걸음을 한다리를 다른다리앞에놓으세요 라고말하는것같다.프로그램을 작성하는 예술 은 기본요소를조합하고엮어사용자에게 유용한무언가를만드는것이다. 단어를세는프로그램은상기프로그램의기본요소를하나만빼고모두사용하 여 작성되었다.
31 10. 프로그램이 잘못되면? 13 제 10절 프로그램이 잘못되면? 처음파이썬과대화에서살펴봤듯이,파이썬코드를명확하게 작성해서 의사 소통해야한다. 작은차이혹은실수는여러분이 작성한프로그램을파이썬이 들여다보다 조기에 포기하게 만든다. 초보파이썬프로그래머는파이썬이오류에대해서는 인정사정보지않는다고 생각한다.파이썬이모든사람을좋아하는것같지만,파이썬은개인적으로만 사람들을알고,분노를간직하고 있다. 이러한사실로 인해서파이썬은여러분 이 완벽하게 작성된 프로그램을 받아서 잘 맞지 않는군요 라고 거절하여 고통 을준다. >>> primt 'Hello world!' File "<stdin>", line 1 primt 'Hello world!' ^ SyntaxError: invalid syntax >>> primt 'Hello world' File "<stdin>", line 1 primt 'Hello world' ^ SyntaxError: invalid syntax >>> I hate you Python! File "<stdin>", line 1 I hate you Python! ^ SyntaxError: invalid syntax >>> if you come out of there, I would teach you a lesson File "<stdin>", line 1 if you come out of there, I would teach you a lesson ^ SyntaxError: invalid syntax >>> 파이썬과다퉈봐야얻을것은없어요.파이썬은도구고감정이없다.여러분이 필요로할때마다여러분에게봉사하고기쁨을주기 위해서존재할뿐이다.오 류메세지가심하게들릴지는모르지만단지파이썬이도와달라는요청일뿐이 다. 입력한것을쭉읽어보고여러분이 입력한것을 이해할수없다고만말할 뿐이다. 파이썬은어떤면에서강아지와닮았다.맹목적으로여러분을사랑하고,강아지 와마찬가지로몇몇단어만 이해하며,웃는표정(»>명령프롬프트)으로여러분 이 파이썬이 이해하는 무언가를 말하기만을 기다린다. 파이썬이 SyntaxError: invalid syntax 을뱉어낼때는,마치강아지가꼬리를흔들면서 뭔가말씀하 시는것같은데요...주인님말씀을 이해하지못하겠어요,다시말씀해주세요 (»>) 말하는것과같다. 여러분이 작성한프로그램이점점 유용해지고복잡해짐에따라 3가지 유형의 오류와 마주친다. 구문 오류(Syntax Error): 첫번째 마주치는 오류로 고치기 가장 쉽습니다. 구문 오류는파이썬문법에맞지않는다는것을 의미한다.파이썬은구문오류
32 14 제 1 장. 왜프로그래밍을배워야하는가? 가발생한줄을찾아정확한 위치를알려준다.하지만,파이썬이제시하는 오류가그이전프로그램부문에서발생했을수도 있기때문에파이썬 이제시하는곳뿐만아니라그앞쪽도살펴볼필요가 있다.따라서구문 오류로파이썬이지칭하는행과문자는오류를고치기 위한시작점으로 의미가 있다. 논리 오류(Logic Error): 논리 오류의 경우 프로그램 구문은 완벽하지만 명령 어실행순서에실수가 있거나혹은문장이서로연관되는방식에오류가 있는 것이다. 논리 오류의 예를 들어보자. 물병에서 한모금 마시고, 가방 에넣고,도서관으로걸어가서,물병을닫는다 의미론적 오류(Semantic Error): 의미론적 오류는 구문론적으로 완벽하고 올 바른순서로프로그램의명령문이 작성되었지만단순하게프로그램에오 류가 있다.프로그램은완벽하게 작동하지만여러분이 의도한바를수 행하지는못한다.간단한예로여러분이식당으로가는방향을알려주고 있다....주유소사거리에도착했을때,왼쪽으로돌아 1.6km쭉가면왼 쪽편에빨간색빌딩에식당이 있습니다. 친구가매우늦어전화로지금농 장에 있고헛간으로걸어가고 있는데식당을발견할수없다고전화를합 니다.그러면여러분은 주유소에서왼쪽으로혹은오른쪽으로돈거야? 말하면,그친구는 말한대로완벽하게따라서갔고,말한대로필기까지 했는데,왼쪽으로돌아 1.6km지점에주요소가 있다고했어,그러면여러 분은 미안해,내가가지고 있는건구문론적으로는완벽한데,슬프게도 사소하지만탐지되지않은 의미론적오류가 있네! 라고말할것이다. 다시한번 위세종류의오류에대해서,파이썬은단지여러분이요청한것을 충실히 수행하기 위해서 최선을 다합니다. 제 11절 학습으로의여정 책을 읽어가면서처음에개념들이 잘와닿지않는다고기죽을필요는없다. 말하는것을배울때,처음몇년동안웅얼거리는것은문제도아니다.간단한어 휘에서간단한문장으로옮겨가데 6개월이걸리고,문장에서문단으로옮겨가 는데 5-6년 이상걸려도괜찮다.흥미로운완전한짧은스토리를 자신의언어로 작성하는데 몇 년이 걸린다. 파이썬을빨리배울수있도록다음몇장에걸쳐서모든정보를제공한다.하지 만새로운언어를습득하는것과마찬가지로 자연스럽게느껴지기까지파이썬 을흡수하고 이해하기까지시간이걸린다.큰그림(Big Picture)을 이루는 작은 조각들을정의하는동안에,큰그림을볼수있도록여러주제를방문하고,또다 시 재방문하면서혼란이생길수도 있다. 이책은순차선형적으로쓰여져서본 과정을선형적으로배워갈수도 있지만,비선형적으로본교재를활용하는것도 괜찮다.가볍게앞쪽과뒷쪽을넘나들며책을 읽을수도 있다.구체적이고세세 한점을완벽하게 이해하지않고고급과정을가볍게 읽으면서프로그래밍의 왜(Why) 에대해서더잘이해할수도 있다.앞에서배운것을다시리뷰하고 연습문제를다시풀면서지금난공불락이라여겼던어려운주제를통해서사실 더많은것을학습했다는것을깨달을것이다.
33 12. 용어사전 15 대체적으로처음프로그래밍언어를배울때는,마치망치로돌을내리치고,끌 로깎아내고하면서아름다운조각품을만들면서겪게되는것과 유사한몇번의 유레카,아하 순간이 있다. 만약어떤것이특별히힘들다면,밤새도록앉아서노력하는것은별로 의미가 없다. 잠시쉬고,낮잠을 자고,간식을먹고다른사람이나강아지에게문제를 설명하고 자문을구한후에깨끗한정신과눈으로돌아와서다시시도해보라. 단언컨데 이책에 있는프로그래밍개념을깨우치게되면,돌이켜생각해보면 프로그래밍은정말쉽고멋지다는것을알게될것이다.그래서단순하게프로 그래밍언어는정말시간을들여서배울가치가 있다. 제 12절 용어사전 버그(bug): 프로그램 오류 중앙처리장치(central processing unit, CPU): 컴퓨터의 심장, 작성한 프로그 램을실행하는 장치, "CPU"혹은프로세서라고부른다. 컴파일(compile): 나중에 실행을 위해서 하이레벨 언어로 작성된 프로그램을 로우레벨 언어로 번역한다. 하이레벨 언어(high-level language): 사람이 읽고 쓰기 쉽게 설계된 파이썬과 같은프로그래밍언어 인터랙티브 모드(interactive mode): 프롬프트에서 명령어나 표현식을 타이핑 함으로써파이썬 인터프리터를사용하는방식 해석한다(interpret): 하이레벨 언어로 작성된 프로그램을 한번에 한줄씩 번역 해서 실행한다. 로우레벨 언어(low-level language): 컴퓨터가 실행하기 좋게 설계된 프로그래 밍언어, 기계어코드, 어셈블리언어 로불린다. 기계어 코드(machine code): 중앙처리장치에 의해서 바로 실행될 수 있는 가장 낮은수준의언어로된소프트웨어 주기억장치(main memory): 프로그램과 데이터를 저장한다. 전기가 나가게 되 면주기억장치에저장된정보는사라진다. 파싱(parsing): 프로그램을 검사하고 구문론적 구조를 분석한다. 이식성(portability): 하나 이상의컴퓨터에서실행될수있는프로그램의특성 출력문(print statement): 파이썬 인터프리터가 화면에 값을 출력할 수 있게 만 드는명령문 문제해결(problem solving:) 문제를만들고,답을찾고,답을표현하는과정 프로그램(program:) 컴퓨테이션(Computation)을 명세하는 명령어 집합
34 16 제 1 장. 왜프로그래밍을배워야하는가? 프롬프트(prompt): 프로그램이 메세지를 출력하고 사용자가 프로그램에 입력 하도록 잠시멈춘때. 보조 기억장치(secondary memory): 전기가 나갔을 때도 정보를 기억하고 프 로그램을 저장하는 저장소. 일반적으로 주기억장치보다 속도가 느리다. USB의 플래쉬 메모리나 디스크 드라이브가 여기에 속한다. 의미론(semantics): 프로그램의 의미 의미론적 오류(semantic error): 프로그래머가 의도한 것과 다른 행동을 하는 프로그램 오류 소스 코드(source code): 하이레벨 언어로 기술된 프로그램 제 13절 연습문제 Exercise 1.1 컴퓨터 보조기억장치 기능은 무엇입니까? a)프로그램의모든연산과로직을실행한다. b) 인터넷을통해웹페이지를불러온다. c)파워가없을때도정보를 장시간저장한다. d) 사용자로부터 입력정보를 받는다. Exercise 1.2 프로그램은무엇입니까? Exercise 1.3 컴파일러와 인터프리터의차이점을설명하세요. Exercise 1.4 기계어 코드는 다음중 어는 것입니까? a)파이썬 인터프리터 b)키보드 c) 파이썬 소스코드 파일 d)워드프로세싱문서 Exercise 1.5 다음코드에서 잘못된점을설명하세요. >>> primt 'Hello world!' File "<stdin>", line 1 primt 'Hello world!' ^ SyntaxError: invalid syntax >>> Exercise 1.6 다음파이썬프로그램이실행된후에,변수 "X"는어디에저장됩 니까? x = 123 a)중앙처리장치 b)주메모리
35 13. 연습문제 17 c)보조메모리 d) 입력장치 e)출력장치 Exercise 1.7 다음프로그램에서출력되는것은무엇입니까? x = 43 x = x + 1 print x a) 43 b) 44 c) x + 1 d)오류,왜냐하면 x = x + 1 은수학적으로불가능하다. Exercise 1.8 사람의어느능력부위를예제로사용하여다음각각을설명하세 요. (1)중앙처리장치, (2)주메모리, (3)보조메모리, (4) 입력장치 (5)출력장치 예를들어중앙처리장치에상응하는사람의몸부위는어디입니까? Exercise 1.9 구문오류("Syntax Error")는 어떻게 고칩니까?
36 18 제 1 장. 왜프로그래밍을배워야하는가?
37 제 2 장 변수,표현식,문장(Statement) 제 1절 값(Value)과 자료형(Type) 값(Value)은문자와숫자처럼프로그램이다루는가장기본이되는단위이다. 지금까지 살펴본 값은 1, 2 그리고'Hello,World!' 이다. 상기 값은 다른 자료형(Type)에 속하는데, 2는 정수, 'Hello,World!' 는 문 자열(String)에 속하는데, 문자(Letter)를 일련의 열(sequence)의 형태로 되어 있 어서 문자열이라고 부른다. 인용부호에 감싸여 있어서, 여러분과 인터프리터는 문자열을 식별할 수 있다. print 문은정수에도사용할수있다. python명령어를실행하여 인터프리터 를구동시키자. python >>> print 4 4 값이어떤형인지확신을못한다면, 인터프리터가알려준다. >>> type('hello, World!') <type 'str'> >>> type(17) <type 'int'> 놀랍지도 않게, strings은 str 형식이고, 정수는 int 형식이다. 다소 명백하지는 않지만,소숫점을가진숫자는float형식이다.왜냐하면 이들숫자가부동소수 점형식으로표현되기때문이다. >>> type(3.2) <type 'float'> '17','3.2' 같은 값은 어떨가? 숫자처럼 보이지만 문자열처럼 인용부호에 감 싸여 있다.
38 20 제 2 장. 변수,표현식,문장(Statement) >>> type('17') <type 'str'> >>> type('3.2') <type 'str'> '17','3.2' 은문자열이다. 1,000,000처럼아주큰정수를 입력할때,세자리숫자마다콤마(,)를사용하 고싶을것이다.하지만,파이썬에서적법하게정수를표현하는것은아니지만 문법적으로는 적합하다. >>> print 1,000, 하지만, 파이썬 실행 결과는 우리가 기대했던 것이 아니다. 파이썬에서는 1,000,000 을콤마(, )로구분된정수로 인식한다.따라서사이사이공백을 넣어 출력했다. 이사례가여러분이처음경험하게되는 의미론적오류(semantic error)다.코드 가에러메세지없이실행이되지만, 올바른(right) 작동을하는것은아니다. 제 2절 변수(Variable) 프로그래밍언어의가장강력한기능중의하나는변수를다룰수있는능력이 다.변수(Variable)는값을참조하는 이름이다. 대입문(Assignment statement)는 새로운 변수를 생성하고 값을 변수에 대입 한다. >>> message = 'And now for something completely different' >>> n = 17 >>> pi = 상기예제는세가지대입사례를보여준다.첫번째대입예제는 message변수 에문자열을대입한다.두번째예제는변수 n에정수 17을대입한다.세번째 예제는pi변수에 π근사값을대입한다. 변수 값을 출력하기 위해서 print문을 사용한다. >>> print n 17 >>> print pi 변수 자료형(type)은 변수가 참조하는 값의 자료형이다. >>> type(message) <type 'str'> >>> type(n) <type 'int'> >>> type(pi) <type 'float'>
39 3. 변수명(Variable name)과예약어(keywords) 21 제 3절 변수명(Variable name)과예약어(keywords) 대체로프로그래머는 의미있는변수명을고른다.프로그래머는변수가사용되 는것에대해문서화도한다. 변수명은 임의로길수있다.변수명은문자와숫자를포함할수있지만,문자 로변수명을시작해야한다.첫변수명을대문자로사용해도되지만소문자로 변수명을시작하는것도좋은생각이다. (후에왜그런지보게될것이다.) 변수명에 밑줄(underscore character, _)이 들어갈 수 있다. 종종 my_name 혹은 airspeed_of_unladen_swallow 처럼 밑줄은 여러 단어와 함께 사용된다. 변수 명을밑줄로시작해서 작성할수있지만,다른사용자가사용할라이브러리를 작성하는 경우가 아니라면, 일반적으로 밑줄로 시작하는 변수명은 피한다. 변수명을 적합하게 작성하지 못하다면, 구문 오류가 발생한다. >>> 76trombones = 'big parade' SyntaxError: invalid syntax >>> more@ = SyntaxError: invalid syntax >>> class = 'Advanced Theoretical Zymurgy' SyntaxError: invalid syntax 76trombones변수명은문자로시작하지않아서적합하지않다. more@은특수 문자 (@)를변수명에포함해서적합하지않다.하지만, class변수명은뭐가 잘 못된 것일까? 구문 오류 이유는 class가 파이썬의 예약어 중의 하나라고 밝혀졌다. 인터프리 터가예약어를사용하여프로그램구조를파악하기 위해서사용하지만,변수명 으로는사용할수없다. 파이썬에는 31개키워드 1 가예약어로 이미사용중에 있다. and del from not while as elif global or with assert else if pass yield break except import print class exec in raise continue finally is return def for lambda try 상기예약어목록을주머니에넣고 잘가지고다니고싶을것이다.만약 인터 프리터가변수명중하나에대해불평을하지만 이유를모르는경우,예약어 목록에 변수명이 있는지 확인해 보세요. 제 4절 문장(Statement) 문장(statement)은 파이썬 인터프리터가 실행하는 코드 단위다. 지금까지 print, assignment두종류의문장을살펴봤습니다. 1 Python 3.0에서exec 은더이상예약어가아니지만,nonlocal 은여전히예약어다.
40 22 제 2 장. 변수,표현식,문장(Statement) 인터랙트브모드에서문장을 입력하면, 인터프리터는문장을실행하고,만약 출력할것이 있다면결과를화면에출력합니다. 스크립트는보통여러줄의문장으로구성됩니다.하나 이상의문장이 있다면, 스트테이트먼트가 실행되며서 결과가 한번에 하나씩 나타납니다. 예를 들어, 다음의 스크립트를 생각해 봅시다. print 1 x = 2 print x 상기 스크립트는 다음 결과를 출력합니다. 1 2 대입문장(x=2)은결과를출력하지않습니다. 제 5 절 연산자(Operator)와 피연산자(Operands) 연산자(Operators)는 덧셈, 곱셈 같은 계산(Computation)을 표현하는 특별한 기 호입니다.연산가자적용되는값을피연산자(operands)라고합니다. 다음의예제에서보듯이, +, -, *, /, **연산자는덧셈,뺄셈,곱셈,나눗셈,지수 승을수행합니다 hour-1 hour*60+minute minute/60 5**2 (5+9)*(15-7) 나눗셈 연산자는 여러분이 기대하는 것을 수행하지 않을 수도 있습니다. >>> minute = 59 >>> minute/60 0 minute값은 59,보통 59를 60으로나누면 0대신에 입니다. 이런차이가 발생하는 이유는파이썬이소수점 이하버림나눗셈 2 을하기때문입니다. 두개의피연산자가정수이면,결과도정수입니다.부동소수점나눗셈은소수 점 이하를절사합니다.그래서예제에서소수점 이하 잘라버려 0 이됩니다. 만약두개의피연산자중하나가부동소수점수이면,파이썬은부동소수점 나눗셈을 수행하고 결과는 부동 소수점형 값이 된다. >>> minute/ 파이썬 3.0에서 이나눗셈값은소수점입니다.파이썬 3.0에도입된새로운연산자//는정 수형나눗셈을수행합니다.
41 6. 표현식(Expression) 23 제 6절 표현식(Expression) 표현식 (expression)은값,변수,연산자조합니다.값은 자체로표현식이고,변 수도동일하다.따라서다음표현식은모두적합하다. (변수 x는사전에어떤 값이대입되었다고가정한다.) 17 x x + 17 인터랙티브 모드에서 표현식을 입력하면, 인터프리터는 표현식을 평가(evaluate)하고값을표시한다. >>> 하지만,스크립트에서는표현식 자체로어떠한것도수행하지는않는다.초심 자에게 혼란스러운 점이다. Exercise 2.1 파이썬 인터프리터에 다음 문장을 입력하고 결과를 보세요. 5 x = 5 x + 1 제 7절 연산자적용우선순위 (Order of Operations) 1개 이상의연산자가표현식에등장할때,연산자평가순서는우선순위규칙 (rules of precedence)에따른다.수학연산자에대해서파이썬은수학적관례를 동일하게 따른다. 영어 두문어 PEMDAS는 기억하기 좋은 방식이다. 괄호(Parentheses)는가장높은순위를가지고여러분이원하는순위에맞 춰실행할때사용한다.괄호내의식이먼저실행되기때문에 2 * (3-1) 은 4가정답이고,(1+1)**(5-2)는 8이다.괄호를사용하여표현식을좀더 읽기쉽게하려고사용하기도한다. (minute * 100) / 60는실행순서 가결과값에영향을주지않지만가독성이상대적으로더좋다. 지수승(Exponentiation)이 다음으로 높은 우선순위를 가진다. 그래서 2**1+1는 4가 아니라 3이고, 3*1**3는 27이 아니고 3이다. 곱셈(Multiplication)과 나눗셈(Division)은 동일한 우선순위를 가지지만, 덧셈(Addition), 뺄셈(Substraction)보다 높은 우선 순위를 가진다. 덧셈과 뺄샘은같은실행우선순위를갖는다. 2*3-1는 4가아니고 5이고, 6+4/2 는 5가아니라 8이다. 같은실행순위를갖는연산자는왼쪽에서부터오른쪽으로실행된다 표현식은 3이 아니고 1이다. 왜냐하면 5-3이 먼저 실행되고 나서 2 에서 1을 빼기 때문이다. 여러분이 의도한순서대로연산이수행될수있도록,좀의심스러운경우는항상 괄호를 사용한다.
42 24 제 2 장. 변수,표현식,문장(Statement) 제 8절 나머지연산자 (Modulus Operator) 나머지 연산자(modulus operator)는 정수에 사용하며, 첫번째 피연산자를 두 번째피연산자가나눌때나머지값이생성된다.파이썬에서나머지연산자는 퍼센트 기호(%)다. 구문은 다른 연산자와 동일하다. >>> quotient = 7 / 3 >>> print quotient 2 >>> remainder = 7 % 3 >>> print remainder 1 7을 3으로나누면몫이 2가되고나머지가 1이된다. 나머지연산자가놀랍도록 유용다다.예를들어한숫자를다른숫자로나눌수 있는지없는지를확인할수도 있다.x % y값이 0 이라면,x를y로나눌수있다. 또한,숫자에서가장오른쪽숫자를분리하는데도사용된다.예를들어 x % 10 은x가 10진수인경우가장오른쪽숫자를뽑아낼수있고,동일한방식으로x % 100은가장오른쪽 2개숫자를뽑아낼수도 있다. 제 9절 문자열연산자 (String Operator) +연산자는문자열에도동작하지만,수학에서말하는덧셈은아니다.대신에 문자열끝과끝을붙이는연결(concatenation) 작업을수행한다.예를들어, >>> first = 10 >>> second = 15 >>> print first+second 25 >>> first = '100' >>> second = '150' >>> print first + second 상기 프로그램 출력은 이다. 제 10절 사용자에게서 입력값받기 때때로키보드를통해서사용자로부터변수에대한값을 입력받고싶을때가 있다.키보드 3 로부터 입력값을받는raw_input 이라는내장(built-in)함수를파 이썬에서제공한다. 입력함수가호출되면,파이썬은실행을멈추고사용자가 무언가 입력하기를기다린다.사용자가 Return (리턴)혹은 Enter (엔터)키를 누르게되면프로그램이다시실행되고, raw_input은사용자가 입력한것을 문자열로 반환한다. 3 파이썬 3.0에서 입력함수는input으로명명되었다.
43 11. 주석 25 >>> input = raw_input() Some silly stuff >>> print input Some silly stuff 사용자로부터 입력받기전에프롬프트에서사용자가어떤값을 입력해야하는 지정보를제공하는것도좋은생각이다. 입력을받기 위해 잠시멈춰있을때, 사용자에게 표시되도록 raw_input 함수에 문자열을 전달할 수 있다. >>> name = raw_input('what is your name?\n') What is your name? Chuck >>> print name Chuck 프롬프트의끝에 \n 은 개행(newline)을 의미한다.개행은줄을바꾸게하는특 수 문자다. 이런 이유 때문에 사용자 입력이 프롬프트 밑에 출력된다. 만약사용자가정수를 입력하기를바란다면, int()함수를사용하여반환되는 값을정수(int)로 자료형을변환한다. >>> prompt = 'What...is the airspeed velocity of an unladen swallow?\n' >>> speed = raw_input(prompt) What...is the airspeed velocity of an unladen swallow? 17 >>> int(speed) 17 >>> int(speed) 하지만,사용자가숫자문자열이아닌다른것을 입력하게되면오류가발생 한다. >>> speed = raw_input(prompt) What...is the airspeed velocity of an unladen swallow? What do you mean, an African or a European swallow? >>> int(speed) ValueError: invalid literal for int() 나중에 이런종류의오류룰어떻게다루는지배울것이다. 제 11절 주석 프로그램이커지고복잡해짐에따라가독성은떨어진다.형식언어(formal language)는촘촘하고코드 일부분도 읽기어렵고무슨역할을왜수행하는지 이해 하기 어렵다. 이런 이유로프로그램이무엇을하는지를 자연어로프로그램에노트를달아 두는것은좋은생각이다. 이런노트를주석(Comments)이라고하고 #기호로 시작한다.
44 26 제 2 장. 변수,표현식,문장(Statement) # 경과한 시간을 퍼센트로 계산 percentage = (minute * 100) / 60 상기사례의경우,주석 자체가한줄이다.주석을프로그램의맨뒤에놓을수도 있다. percentage = (minute * 100) / 60 # 경과한 시간을 퍼센트로 계산 #뒤의모든것은무시되기때문에프로그램에는아무런영향이없다. 명확하지않은코드의기능을문서화할때주석은가장 유용하게된다.프로그램 을 읽는사람이코드가무엇을하는지 이해한다고가정하는것은 일리가 있다. 왜그런지를 이유를설명하는것은더욱 유용하다. 다음의 주석은 코드와 중복되어 쓸모가 없다. v = 5 # assign 5 to v 다음의주석은코드에없는 유용한정보가 있다. v = 5 # velocity in meters/second. 좋은변수명은주석을할필요를없게만들지만,지나치게긴변수명은 읽기 어려운 복잡한 표현식이 될 수 있다. 그래서 상충관계(trade-off)가 존재한다. 제 12절 연상되는변수명만들기 변수를 이름짓는데단순한규칙을지키고예약어를피하기만하다면,변수이름 을 작명할수있는무척이나많은경우의수가존재한다.처음에 이렇게넓은선 택폭이오히려프로그램을 읽는사람이나프로그램을 작성하는사람모두에게 혼란을줄수있다.예를들어,다음의 3개프로그램은각프로그램이달성하려 하는관점에서동일하지만,여러분이 읽고 이해하는데는많은차이점이 있다. a = 35.0 b = c = a * b print c hours = 35.0 rate = pay = hours * rate print pay x1q3z9ahd = 35.0 x1q3z9afd = x1q3p9afd = x1q3z9ahd * x1q3z9afd print x1q3p9afd 파이썬 인터프리터는상기 3개프로그램을정확하게동일하게바라보지만,사 람은 이들프로그램을매우다르게보고 이해한다.사람은가장빨리두번째 프로그램의 의도를 알아차린다. 왜냐하면 각 변수에 무슨 데이터가 저장될지에 관해서,프로그래머의 의도를반영하는변수명을사용했기때문이다.
45 12. 연상되는 변수명 만들기 27 현명하게선택된변수명을연상기호변수명("mnemonic variable name")이라고 한다.연상되기좋은영어단어 "mnemonic" 4 은기억을돕는다는뜻이다.왜변 수를생성했는지기억하기좋게하기 위해서연상하기좋은변수명을선택한다. 매우훌륭하게들리고,연상하기좋은변수명을만드는게좋은아이디어같지 만,기억하기좋은변수명은초보프로그래머가코드를파싱(parsing)하고 이해 하는데걸림돌이되기도한다.왜냐하면 31개밖에되지않지만예약어도기 억하지못하고,변수명이때때로너무서술적이라마치 일반적으로사용하는 언어처럼보이고 잘선택된변수명처럼보이지않기때문이다. 어떤데이터를반복하는다음파이썬코드를살펴보자.곧반복루프를살펴보 겠지만,다음코드가무엇을 의미하는지알기 위해서퍼즐을풀어보자. for word in words: print word 무엇이 일어나고 있는것일까? for, word, in등등어느토큰이예약어일까?변수 명은무엇일까?파이썬은기본적으로단어의개념을 이해할까?초보프로그래 머는어느부분코드가 이예제와동일해야만하는지그리고,어느부분코드가 프로그래머선택에 의한것인지분간하는데고생을한다. 다음의코드는 위의코드와동일하다. for slice in pizza: print slice 초보프로그래머가 이코드를보고어떤부분이파이썬예약어이고어느부분이 프로그래머가 선택한 변수명인지 알기 쉽다. 파이썬이 피자와 피자조각에 대한 근본적인 이해가없고,피자는하나혹은여러조각으로구성된다는근본적인 사실을알지못한다는것은 자명하다. 하지만, 작성한프로그램이데이터를 읽고데이터에 있는단어를찾는다면피자 (pizza)와 피자조각(slice)은 연상하기 좋은 변수명이 아니다. 이것을 변수명 으로선핸하게되면프로그램의 의미를왜곡시킬수있다. 좀시간을보낸후에가장흔한예약어에대해서알게될것이고, 이들예약어가 어느순간여러분에게눈에띄게될것이다. for word in words: print word 파이썬에서정의된코드 일부분(for, in, print, :)은예약어로굵게표시되어 있고,프로그래머가생성한변수명(word, words)는굵게표시되어 있지않다. 대다수텍스트편집기는파이썬구문을 인지하고 있어서,파이썬예약어와프 로그래머가 작성한변수를구분하기 위해서색깔을다르게표시한다. 잠시후에 여러분은파이썬을 읽고변수와예약어를빠르게구분할수있을것이다. 4 d ëńĺëńd.
46 28 제 2 장. 변수,표현식,문장(Statement) 제 13 절 디버깅(Debugging) 이 지점에서 여러분이 저지르기 쉬운 구문 오류는 odd~job, US$ 같은 특수문자 를포함해서 잘못된변수명을생성하는것과 class, yield같은예약어를변수 명으로 사용하는 것이다. 변수명에공백을넣는다면,파이썬은연산자없는두개의피연산자로생각 한다. >>> bad name = 5 SyntaxError: invalid syntax 구문오류에대해서,오류메세지는그다지도움이되지못한다.가장흔한오류 메세지는 SyntaxError: invalid syntax, SyntaxError: invalid token인 데둘다그다지오류에대한많은정보를주지는못한다. 여러분이많이범하는실행오류는정의전에사용( use before def )하는것으로 변수에값을대입하기전에변수를사용할경우발생한다.여러분이변수명을 잘못쓸때도발생할수있다. >>> principal = >>> interest = principle * rate NameError: name 'principle' is not defined 변수명은 대소문자를 구분한다. 그래서, LaTeX는 latex와 같지 않다. 이지점에서여러분이범하기쉬운 의미론적오류는연산자우선순위일것이다. 예를들어 1 2π를계산하기 위해서다음과같이프로그램을 작성하게되면... >>> 1.0 / 2.0 * pi 나눗셈이먼저 일어나서 π/2이되는데 의도한것과같지않다.파이썬으로하여 금여러분이 작성한 의도를알게할수는없다.그래서 이런경우오류메세지는 없지만,여러분은 잘못된답을얻게된다. 제 14절 용어설명 대입(assignment): 변수에 값을 대입하는 문장 연결(concatenate): 두 개의 피연산자 끝과 끝을 합치는 것 주석(comment): 다른프로그래머나소스코드를 읽는다른사람을 위한프로그 램 정보로 프로그램의 실행에는 아무런 영향이 없다. 평가(evaluate): 하나의 값을 만들도록 연산을 실행함으로써 표현식을 간단히 하는것 표현식(expression): 하나의결과값을만드는변수,연산자,값의조합 부동 소수점(floating-point): 소수점을 가진 숫자를 표현하는 자료형
47 15. 연습문제 29 버림나눗셈(floor division) 두숫자를나누어소수점이하부분을절사하는연 산자 정수(integer): 완전수를 나타내는 자료형 예약어(keyword): 컴파일러가 프로그램을 파싱하는데 사용하기 위해서 이미 예약된단어; if, def, while같은예약어를변수명으로사용할수없다. 연상기호(mnemonic): 기억 보조. 변수에 저장된 것을 기억하기데 도움이 되도 록 변수에 연상되는 이름을 부여한다. 나머지 연산자(modulus operator): 퍼센트 기호 (%)로 표시되고 정수를 가지고 한숫자를다른숫자로나누었을때나머지를생성하는연산자 피연산자(operand): 연산자가 연산을 수행하는 값중의 하나 연산자(operator): 덧셈,곱셈,문자열결합같은간단한연산을표현하는특별 기호 우선순위 규칙(rules of precedence): 다수의 연산자와 피연산자를 포함한 표현 식이평가되는실행순서를규정한규칙집합 문장(statement): 명령이나 액션을 나타내는 코드 부문. 지금까지 assignment, print문을보았다. 문자열(string): 일련의 문자를 나타내는 형식 자료형(type): 값의범주.지금까지여러분이살펴본 자료형은정수 (int),부동 소수점수 (float),문자열 (str) 이다. 값(value): 숫자나 문자 같은 프로그램이 다루는 데이터의 기본 단위중 하나 변수(variable): 값을 참조하는 이름 제 15절 연습문제 Exercise 2.2 raw_input을사용하여사용자의 이름을 입력받고환영하는프로 그램을 작성하세요. Enter your name: Chuck Hello Chuck Exercise 2.3 급여를지불하기 위해서사용자로부터근로시간과시간당 임금을 계산하는프로그램을 작성하세요. Enter Hours: 35 Enter Rate: 2.75 Pay: 96.25
48 30 제 2 장. 변수,표현식,문장(Statement) 지금은급여가정확하게소수점두자리까지표현되지않아도된다.만약원하 다면,파이썬내장round함수를사용하여소수점아래두자리까지반올림하여 작성할수있다. Exercise 2.4 다음대입문장을실행한다고가정합시다. width = 17 height = 12.0 다음 표현식 각각에 대해서, 표현식의 값(value)과 (표현식 값의) 자료형(type)을 작성하세요. 1. width/2 2. width/ height/ * 5 정답을 확인하기 위해서 파이썬 인터프리터를 사용하세요. Exercise 2.5 사용자로부터섭씨온도를 입력받아화씨온도로변환하고,변환된 온도를 출력하는 프로그램을 작성하세요.
49 제 3 장 조건부실행 제 1 절 불 표현식(Boolean expressions) 불 표현식(boolean expression)은 참(True) 혹은 거짓(False)를 지닌 표현식이다. 다음예제는 ==연산자를사용하여두개피연산자를비교하여값이동일하면 참(True),그렇지않으면거짓(False)을산출한다. >>> 5 == 5 True >>> 5 == 6 False 참(True)과 거짓(False)은 불(bool) 자료형(type)에 속하는 특별한 값이지만, 문자열은아니다. >>> type(true) <type 'bool'> >>> type(false) <type 'bool'> ==연산자는 비교 연산자(comparison operators) 중 하나이고, 다른 연산자는 다음과 같다. x!= y x > y x < y x >= y x <= y x is y x is not y # x는 y와 값이 같지 않다. # x는 y보다 크다. # x는 y보다 작다. # x는 y보다 크거나 같다. # x는 y보다 작거나 같다. # x는 y와 같다. # x는 y와 개체가 동일하지 않다. 상기연산자가친숙할지모르지만,파이썬기호는수학기호와다르다. 일반적 인오류로비교를해서동일하다는 의미로==연산자대신에=를사용하는것이 다. =연산자는대입연산자이고, ==연산자는비교연산자다. =<, =>같은비교 연산자는 파이썬에는 없다.
50 32 제 3 장. 조건부실행 제 2절 논리연산자 세개논리연산자(logical operators): and, or, not가있다.논리연산자 의미는 영어 의미와 유사하다.예를들어, x > 0 and x < 10 x 가 0 보다 크다. 그리고(and), 10 보다 작으면 참이다. n%2 == 0 or n%3 == 0은두조건문중의하나만참이되면,즉,숫자가 2혹은 (or) 3으로 나누어지면 참이다. 마지막으로 not연산자는불연산표현식을부정한다. x > y가거짓이면, not (x > y)은참이다.즉,x이y보다 작거나같으면참이다. 엄밀히말해서,논리연산자의두피연산자는모두불표현식이지만,파이썬에 서그다지엄격하지는않다. 0 이아닌 임의의숫자모두 "참(true)"으로해석 된다. >>> 17 and True True 이러한 유연함이 유용할수있으나,혼란을줄수도 있으니 유의해서사용해야 한다.무슨 일을하고 있는지정확하게알지못한다면피하는게상책이다. 제 3절 조건문실행 유용한프로그램을 작성하기 위해서거의항상조건을확인하고조건에따라프 로그램 실행을 바꿀 수 있어야 한다. 조건문(Conditional statements)은 그러한 능력을부여한다.가장간단한형태는if문이다. if x > 0 : print 'x is positive' if문 뒤에 불 표현식(boolean expression)을 조건(condition)이라고 한다. no x > 0 yes print 'x is positive' 만약조건문이참이면,들여쓰기된문장이실행된다.만약조건문이거짓이면, 들여쓰기된문장의실행을건너뛴다.
51 4. 대안 실행 33 if문은함수정의, for반복문과동일한구조를가진다. if문은콜론(:)으로끝 나는 헤더 머리부문과 들여쓰기된 몸통 블록(block)으로 구성된다. if문처럼 문장이한줄이상에걸쳐 작성되기때문에복합문장(compound statements) 이라고 한다. if문몸통부문에 작성되는실행문장숫자에제한은없으나최소한한줄은 있어야한다.때때로,몸통부문에어떤문장도없는경우가 있다.아직코드를 작성하지않아서 자리만 잡아놓는경우로,아무것도수행하지않는 pass문을 사용할수있다. if x < 0 : pass # 음수값을 처리 예정! if문을파이썬 인터프리터에서타이핑하고엔터를치게되면,명령프롬프트가 갈매기세마리에서점세개로바뀐다.따라서다음과같이 if문몸통부분을 작 성중에 있다는 것을 나타낸다. >>> x = 3 >>> if x < 10:... print 'Small'... Small >>> 제 4절 대안실행 if문의 두 번째 형태는 대안 실행(alternative execution)이다. 대안 실행의 경우 두가지경우의수가존재하고,조건이어느방향으로실행할것인지결정한다. 구문(Syntax)은아래와같다. if x%2 == 0 : print 'x is even' else : print 'x is odd' x를 2로나누었을때, 0 이되면,x는짝수이고,프로그램은짝수( x is even )라는 결과메시지를출력한다.만약조건이거짓이라면,두번째몸통부문문장이 실행된다. no print 'x is odd' x%2 == 0 yes print 'x is even'
52 34 제 3 장. 조건부실행 조건은참혹은거짓이어서,대안중하나만정확하게실행된다.대안을분기 (Branch)라고도 하는데 이유는 실행 흐름이 분기되기 때문이다. 제 5절 연쇄조건문 때때로,두가지 이상의경우의수가 있으며,두가지 이상의분기가필요하다. 이와같은연산을표현하는방식이연쇄조건문(chained conditional)이다. if x < y: print 'x is less than y' elif x > y: print 'x is greater than y' else: print 'x and y are equal' elif는 else if 의축약어이다. 이번에도단한번의분기만실행된다. x < y yes print 'less' x > y yes print 'greater' print 'equal' elif문의갯수에제한은없다. else절이 있다면,거기서끝마쳐야하지만,연 쇄조건문에필히 있어야하는것은아니다. if choice == 'a': print 'Bad guess' elif choice == 'b': print 'Good guess' elif choice == 'c': print 'Close, but not correct' 각조건은순서대로점검한다.만약첫번째가거짓이면,다음을점검하고계속 점검해나간다.순서대로진행중에하나의조건이참이면,해당분기가수행되 고,if문전체는종료된다.설사하나 이상의조건이참이라고하더라도,첫번째 참분기만수행된다.
53 6. 중첩 조건문 35 제 6절 중첩조건문 하나의조건문이조건문내부에중첩될수있다.다음과같이삼분예제를 작성 할수있다. if x == y: print 'x and y are equal' else: if x < y: print 'x is less than y' else: print 'x is greater than y' 바깥조건문에는두개의분기가 있다.첫분기는간단한문장을담고 있다.두번 째분기는 자체가두개의분기를가지고 있는또다른if문을담고 있다. 자체로 둘다조건문이지만,두분기모두간단한문장이다. yes x == y no yes x < y no print 'equal' print 'less' print 'greater' 문장을들여쓰는것이구조를명확히하지만,중첩조건문의 경우 가독성이급 격히저하된다. 일반적으로, 가능하면중첩조건문을피하는 것을권장한다. 논리연산자를사용하여중첩조건문을 간략히할수있다.예를들어,단일조 건문으로 가지고앞의코드를다음과 같이 재작성할수있다. if 0 < x: if x < 10: print 'x is a positive single-digit number.' print문은 두 개 조건문을 통과될 때만 실행돼서, and 연산자와 동일한 효과를 거둘수있다. if 0 < x and x < 10: print 'x is a positive single-digit number.'
54 36 제 3 장. 조건부실행 제 7절 try와 catch를활용한예외처리 함수 raw_input와 int을사용하여앞에서사용자가타이핑한숫자를 읽어정 수로파싱하는프로그램코드를살펴보았다.또한 이렇게코딩하는 것이얼마나 위험한 것인지도 살펴보았다. >>> speed = raw_input(prompt) What...is the airspeed velocity of an unladen swallow? What do you mean, an African or a European swallow? >>> int(speed) ValueError: invalid literal for int() >>> 파이썬 인터프리터에서상기문장을실행하면, 인터프리터에서새로운프롬프 트로되고, "이런(oops)" 잠시후에,다음문장실행으로넘어간다. 하지만,만약코드가파이썬스크립트로실행이되어오류가발생하면,역추적 해서그지점에서즉시멈추게된다.다음에오는문장은실행하지않는다. 화씨온도를섭씨온도로변환하는 간단한프로그램이 있다. inp = raw_input('enter Fahrenheit Temperature:') fahr = float(inp) cel = (fahr ) * 5.0 / 9.0 print cel 이코드를실행해서적절하지않은 입력값을넣게되면,다소불친절한오류 메시지와 함께 간단히 작동을 멈춘다. python fahren.py Enter Fahrenheit Temperature: python fahren.py Enter Fahrenheit Temperature:fred Traceback (most recent call last): File "fahren.py", line 2, in <module> fahr = float(inp) ValueError: invalid literal for float(): fred 이런종류의예측하거나,예측하지못한오류를다루기 위해서파이썬에는 try / except 로불리는조건실행구조가내장되어 있다.try와except의기본적인 생각은 일부명령문에문제가 있다는 것을사전에알고 있고,만약그때문에오 류가 발생하게 된다면 대신 프로그램에 추가해서 명령문을 실행한다는 것이다. except블록의문장은오류가없다면실행되지않는다. 문장 실행에 대해서 파이썬 try, except 기능을 보험으로 생각할 수도 있다. 온도변환기프로그램을다음과 같이 재작성한다. inp = raw_input('enter Fahrenheit Temperature:') try: fahr = float(inp) cel = (fahr ) * 5.0 / 9.0
55 8. 논리연산식의단락(Short circuit)평가 37 print cel except: print 'Please enter a number' 파이썬은 try블록문장을우선실행한다.만약모든 것이순조롭다면, except 블록을 건너뛰고,다음코드를실행한다.만약 try블록에서 except이발생하 면, 파이썬은 try 블록에서 빠져 나와 except블록 문장을 수행한다. python fahren2.py Enter Fahrenheit Temperature: python fahren2.py Enter Fahrenheit Temperature:fred Please enter a number try문으로 예외사항을 다루는 것을 예외 처리한다(catching an exception)고 부른다. 예제에서 except 절에서는 단순히 오류 메시지를 출력만 한다. 대체로, 예외처리를통해서오류를 고치거나, 재시작하거나,최소한프로그램이정상 적으로종료될수있게한다. 제 8절 논리연산식의단락(Short circuit)평가 x >= 2 and (x/y) > 2와 같은 논리 표현식을 파이썬에서 처리할 때, 왼쪽에 서부터오른쪽으로표현식을평가한다. and정의때문에 x 가 2보다 작다면, x >= 2은 거짓(False)으로, 전체적으로 (x/y) > 2 이 참(True) 혹은 거짓 (False) 이냐에관계없이거짓(False)이된다. 나머지논리표현식을평가해도나아지는 것이없다고파이썬이 자동으로탐 지할때,평가를멈추고나머지논리표현식에대한연산도중지한다.최종값이 이미 결정되었기때문에더이상의논리표현식의평가가멈출때, 이를단락 (Short-circuiting)평가라고한다. 좋은점처럼보일수있지만,단락행동은 가디언패턴(guardian pattern)으로 불리는좀더똑똑한기술로연계된다.파이썬 인터프리터의다음코드를살펴 보자. >>> x = 6 >>> y = 2 >>> x >= 2 and (x/y) > 2 True >>> x = 1 >>> y = 0 >>> x >= 2 and (x/y) > 2 False >>> x = 6 >>> y = 0 >>> x >= 2 and (x/y) > 2 Traceback (most recent call last): File "<stdin>", line 1, in <module>
56 38 제 3 장. 조건부실행 ZeroDivisionError: integer division or modulo by zero >>> 세번째연산은실패하는데 이유는 (x/y)연산을평가할때y가0이어서실행 오류발생한다.하지만,두번째예제의 경우실패하지않는데 이유는 x >= 2 이 거짓(False) 으로, 전체가 거짓(False)이 되어 단락(Short-circuiting) 평가 규칙에 의해(x/y)평가는실행되지않아오류도발생하지않는다. 평가 오류를 발생하기 전에 가디언(gardian) 평가식을 전략적으로 배치해서 논 리표현식을다음과 같이구성한다. >>> x = 1 >>> y = 0 >>> x >= 2 and y!= 0 and (x/y) > 2 False >>> x = 6 >>> y = 0 >>> x >= 2 and y!= 0 and (x/y) > 2 False >>> x >= 2 and (x/y) > 2 and y!= 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: integer division or modulo by zero >>> 첫번째논리표현식은 x >= 2 이거짓(False) 이라 and에서멈춘다.두번째 논리표현식은x >= 2 이참(True),y!= 0은거짓(False) 이라(x/y)까지 갈 필요가없다.세번째논리표현식은(x/y)연산이끝난후에y!= 0 이수행되 어서오류가발생한다. 두번째표현식에서y가0이아닐때만,(x/y)을실행하도록y!= 0 이 가디언 (gardian)역할을수행한다고말할수있다. 제 9절 디버깅(Debugging) 오류가 발생했을 때, 파이썬 화면에 출력되는 역추적(traceback)에는 상당한 정보가담겨있다.하지만,특히스택에많은프레임이 있는 경우엄청나게보여 엄두가나지않을수도 있다.대체로 가장 유용한정보는다음과 같은 것이 있다. 어떤 종류의 오류인가. 어디서발생했는가. 구문오류는대체로발견하기쉽지만,몇가지는애매하다. 공백(space)과탭 (tab)의차이가눈에보이지않아통상무시하고넘어가기쉽기때문에 공백오 류를 잡아내기가까다롭다. >>> x = 5 >>> y = 6 File "<stdin>", line 1
57 10. 용어 정의 39 y = 6 ^ SyntaxError: invalid syntax 상기예제문제는두번째줄에한칸공백이들여써서발생하는 것이다.하지만, y에오류메시지가 있는데프로그래머를 잘못된 곳으로 인도한다.대체로오류 메시지는 문제가 어디에서 발견되었는지를 지칭하지만, 실제 오류는 코드 앞에 종종선행하는줄에 있을수있다. 동일한문제가실행오류에도 있다.데시벨(decibels)로신호대비 잡음비를 계 산한다고 가정하자. 공식은 SNR db = 10log 10 (P signal /P noise ) 이다.파이썬에서아 래와 같이 작성할수있다. import math signal_power = 9 noise_power = 10 ratio = signal_power / noise_power decibels = 10 * math.log10(ratio) print decibels 하지만,실행하게되면,다음과 같은오류메시지 1 가발생한다. Traceback (most recent call last): File "snr.py", line 5, in? decibels = 10 * math.log10(ratio) OverflowError: math range error 오류메지지가 5번째줄에 있다고지칭하지만, 잘못된 것은없다.실제오류를 발견하기 위해서,출력값이 0 인ratio 값을print문을사용해서출력하는 것이 도움이된다.문제는 4번째줄에 있는데,왜냐하면두정수를나눌때내림나눗 셈을 했기 때문입니다. signal_power 와 noise_power 를 부동 소수점값으로 표현하는게해결책이다. 대체로,오류메시지는문제가어디에서발견되었는지를알려주지만,종종문 제의 원인이 어디에서 발생했는지는 알려주지 않는다. 제 10절 용어정의 몸통 부문(body): 복합 문장 내부에 일련의 문장문 불 표현식(boolean expression): 참(True) 혹은 거짓(False)의 값을 가지는 표 현식 분기(branch): 조건문에서 대안 문장의 한 흐름 연쇄 조건문(chained conditional): 일련의 대안 분기가 있는 조건문 비교 연산자(comparison operator): 피연산자를 ==,!=, >, <, >=, <=로 비교하 는연산자 1 파이썬 3.0에서는오류메시지가발생하지않는다.정수피연산자인경우에도나눗셈연산 자가 부동 소수점 나눗셈을 수행한다.
58 40 제 3 장. 조건부실행 조건문(conditional statement): 조건에 따라 명령의 흐름을 제어하는 명령문 조건(condition): 조건문에서 어느 분기를 실행할지 결정하는 불 표현식 복합문(compound statement): 머리부문(head)과 몸통부문(body)으로 구성된 문장. 머리부문은 콜론(:)으로 끝나며, 몸통부문은 머리부문을 기준으로 들여쓰기로 구별된다. 가디언 패턴(guardian pattern): 단락(short circuit) 행동을 잘 이용하도록 논 리표현식을구성하는 것 논리 연산자(logical operator): 불 표현식을 결합하는 연산자 중의 하나 (and, or,not) 중첩 조건문(nested conditional): 하나의 조건문이 다른 조건문 분기에 나타나 는조건문. 역추적(traceback): 예외 사항이 발생했을 때 실행되고, 출력되는 함수 리스트 단락(short circuit): 나머지표현식평가를할필요없이최종 결과를알기때문 에,파이썬이논리표현식평가를진행하는중간에평가를멈출때. 제 11절 연습문제 Exercise 시간 이상 일할경우시급을 1.5배더종업원에게지급하는봉 급계산 프로그램을 다시 작성하세요. Enter Hours: 45 Enter Rate: 10 Pay: Exercise 3.2 try, except를 사용하여 봉급계산 프로그램을 다시 작성하세요. 숫자가아닌 입력값을 잘처리해서숫자아닌 입력값이들어왔을때메시지를 출력하고 정상적으로 프로그램을 종료하도록 합니다. 다음이 프로그램 출력 결 과를 보여줍니다. Enter Hours: 20 Enter Rate: nine Error, please enter numeric input Enter Hours: forty Error, please enter numeric input Exercise 과 1.0사이의점수를출력하는프로그램을 작성하세요.만약 점수가범위밖이면오류를출력합니다.만약점수가 0.0과 1.0사이라면,다음 의테이블에따라등급을출력합니다. Score Grade >= 0.9 A
59 11. 연습문제 41 >= 0.8 B >= 0.7 C >= 0.6 D < 0.6 F Enter score: 0.95 A Enter score: perfect Bad score Enter score: 10.0 Bad score Enter score: 0.75 C Enter score: 0.5 F 상기보이는것처럼반복적으로프로그램을실행해서다양한다른 입력값을테 스트해 보세요.
60 42 제 3 장. 조건부실행
61 제 4 장 함수 제 1절 함수호출 프로그래밍 문맥에서, 함수(function)는 연산을 수행하는 명명된 일련의 문장이 다.함수를정의할때, 이름과 일련의문장을명기한다.나중에,함수를 이름으로 호출(call) 한다. 이미함수호출(function call)의예제를살펴봤다. >>> type(32) <type 'int'> 함수명은 type이다. 괄호안의 표현식을 함수의 인자(argument)라고 한다. 인 자는함수 입력으로함수내부로전달되는 값이나변수이다.앞선 type함수에 대한 결과는 인자의 자료형(type)이다. 통상 함수가 인자를 받아 결과를 반환 한다. 결과를 결과값(return value) 이라 부른다. 제 2절 내장(Built-in)함수 함수를정의할필요없이사용할수있는내장함수가파이썬에는많다. 공통의 문제를해결할수있는함수를파이썬을창시자(Guido van Rossum)가 작성해 서누구나사용할수있도록파이썬에포함했다. max와 min 함수는 리스트 최소값과 최대값을 각각 계산해서 출력한다. >>> max('hello world') 'w' >>> min('hello world') ' ' >>> max함수는문자열의 "가장큰문자",상기예제에서 w, min함수는최소문 자를,상기예제에서는 공백,출력한다.
62 44 제 4 장. 함수 매우 자주사용되는또다른내장함수는얼마나많은항목이 있는지출력하 는 len함수가 있다.만약 len함수의 인수가문자열이면문자열에 있는문자 갯수를 반환한다. >>> len('hello world') 11 >>> 이들함수는문자열에만국한된 것이아니라,뒷장에서보듯이다양한 자료형에 사용된다. 내장함수 이름은사전에점유된예약어로취급해야한다.예를들어 max 를 변수명으로사용하지말아야한다. 제 3절 자료형(type)변환함수 이런 자료형(type)에서저런 자료형(type)으로 값을변환하는내장함수가파 이썬에는 있다. int함수는 임의의 값을 입력받아변환이 가능하면정수형으로 변환하고,그렇지않으면오류가발생한다. >>> int('32') 32 >>> int('hello') ValueError: invalid literal for int(): Hello int는부동소수점 값을정수로변환할수있지만소수점 이하를절사한다. >>> int( ) 3 >>> int(-2.3) -2 float는 정수와 문자열을 부동 소수점으로 변환한다. >>> float(32) 32.0 >>> float(' ') 마지막으로,str은 인자를문자열로변환한다. >>> str(32) '32' >>> str( ) ' ' 제 4절 난수(Random numbers) 동일한 입력을받을때,대부분의 컴퓨터는매번동일한출력값을생성하기때문 에 결정적(deterministic)이라고한다. 결정론이대체로좋은 것이다.왜냐하면,
63 4. 난수(Random numbers) 45 동일한 결과를얻는데동일한 계산을기대하기때문입니다.하지만,어떤 응용 프로그램에대해서 컴퓨터가예측불가능하길바란다. 게임이좋은예가되고, 더많은예는얼마든지많다. 진실되게프로그램을비결정론적으로만드는 것이쉽지않은 것으로밝혀졌지 만,적어도비결정론적인 것처럼보이게하는방법은 있다. 의사난수(pseudorandom numbers)를생성하는알고리즘을사용하는 것이방법중의하나다. 의 사난수는 이미 결정된연산에 의해서생성된다는점에서진정한 의미의난수는 아니지만, 이렇게생성된숫자만봐서는진정한난수와구별하는 것은불가능에 가깝다. random모듈안에 의사난수를생성하는함수가 있다. (이하 의사난수대신 랜덤(random) 으로 간략히 부르기로 한다.) random함수는 0.0 과 1.0사이부동소수점난수를반환한다.random함수는 0.0 은포함하지만 1.0은포함하지않는다.매번 random함수를호출할때마다, 이 미생성된아주긴난수열에서하나씩하나씩뽑아쓰다.사례로다음반복문을 실행하자. import random for i in range(10): x = random.random() print x 상기프로그램은 0.0에서 1.0구간(단, 1.0은포함하지않음)에서 10개난수리 스트를 생성한다 Exercise 4.1 여러분의컴퓨터에프로그램을실행해서,어떤난수가생성되는 지살펴보세요.한번 이상프로그램을실행하여보고,어떤난수가생성되는지 다시 살펴보세요. random함수는난수를다루는많은함수중의하나다. randint함수는최저 (low)와 최고(high) 매개 변수를 입력받아 최저값(low)과 최고값(high) 사 이 (최저값과,최저값모두포함)정수를반환한다. >>> random.randint(5, 10) 5 >>> random.randint(5, 10) 9
64 46 제 4 장. 함수 무작위로 특정 열에서 하나의 요소를 뽑아내기 위해, choice를 사용한다. >>> t = [1, 2, 3] >>> random.choice(t) 2 >>> random.choice(t) 3 또한 random모듈은정규분포,지수분포, 감마분포및기타연속형분포에서 난수를생성하는함수도제공한다. 제 5절 수학함수 파이썬은 가장 친숙한수학함수를제공하는수학모듈이 있다.수학모듈을 사용하기 전에, 수학 모듈 가져오기를 실행한다. >>> import math 상기명령문은 math라는모듈 객체를생성한다.모듈 객체를출력하면,모듈 객체에대한정보를얻을수있다. >>> print math <module 'math' from '/usr/lib/python2.5/lib-dynload/math.so'> 모듈 객체는모듈에정의된함수와변수를담고 있다.함수중에서한함수에 접근하기 위해서는,모듈 이름과함수 이름을명시해야하는데,둘은점(구두점) 으로구분된다. 이런형식을점표기법(dot notation)이라고부른다. >>> ratio = signal_power / noise_power >>> decibels = 10 * math.log10(ratio) >>> radians = 0.7 >>> height = math.sin(radians) 첫예제는신호-대-소음비의로그밑이 10 을 계산한다.수학모듈이 자연로그를 log함수를호출해서사용할수있도록제공한다. 두번째예제는라디안의사인값을찾는 것이다.변수의 이름이힌트를주는데, sin과 다른 삼각함수(cos, tan 등)는 라디안을 인자로 받는다. 도(degree)에서 라디안(radian)으로 변환하기 위해서 360으로 나누고 2π를 곱한다. >>> degrees = 45 >>> radians = degrees / * 2 * math.pi >>> math.sin(radians) math.pi표현식은수학모듈에서 pi변수를얻는데, π 값과비교하여 15 자리 수까지 정확하고 근사적으로 수렴한다. 삼각함수를배웠다면,앞선연산 결과를 2에루트를씌우고 2로나누어비교 검증한다. >>> math.sqrt(2) /
65 6. 신규함수추가 47 제 6절 신규함수추가 지금까지파이썬설치시함께 있는함수만사용했지만새로운함수를추가하는 것도 가능하다. 함수 정의(function definition)는 신규 함수명과 함수가 호출될 때실행될 일련의문장을명세한다.신규로함수를정의하면,프로그램실행중 에반복해서함수를 재사용할수있다. 다음에예제가 있다. def print_lyrics(): print "I'm a lumberjack, and I'm okay." print 'I sleep all night and I work all day.' def는 "이것이 함수 정의다"를 표시하는 예약어다. 함수 이름은 print_lyrics 이다.함수 이름을명명규칙은변수명과동일하다.문자,숫자,그리고몇몇문장 부호는사용할수있지만,첫문자가숫자는될수없다.함수 이름으로예약어를 사용할수없고,함수 이름과동일한변수명은피해야한다. 함수명뒤빈괄호는 이함수가어떠한 인자도 갖지않는다는 것을나타낸다. 나중에, 입력값으로 인자를 가지는함수를 작성해볼것이다. 함수정의첫번째줄을머리부문(헤더, header),나머지부문을몸통부문(바디, body)라고부른다.머리부문은콜론(:)으로끝나고,몸통부문은들여쓰기해야 한다.파이썬관례로들여쓰기는항상 4칸 공백이다.몸통부문에는제약없이 문장을 작성할수있다. print문의문자열은 이중 인용부호로 감싼다.단일 인용부호나, 이중 인용부호 나차이는없다.대부분의 경우단일 인용부호를사용하고,단일 인용부호가문 자열에나타나는 경우, 이중 인용부호를사용하여단일 인용부호가출력되게 감싼다. 만약함수정의를 인터렉티브모드에서타이핑을하면,함수정의가끝나지않 았다는 것을 의미로생략부호(...)가출력된다. >>> def print_lyrics():... print "I'm a lumberjack, and I'm okay."... print 'I sleep all night and I work all day.'... 함수정의를끝내기 위해서빈줄을 입력한다. (스크립트에서는반듯이필요한 것은아니다.) 함수를 정의하게 되면 동일한 이름의 변수도 생성된다. >>> print print_lyrics <function print_lyrics at 0xb7e99e9c> >>> print type(print_lyrics) <type 'function'> print_lyrics 값은'function' 형을 가지는 함수 객체(function object)다. 신규 함수를 호출하는 구문은 내장 함수의 경우와 동일하다.
66 48 제 4 장. 함수 >>> print_lyrics() I'm a lumberjack, and I'm okay. I sleep all night and I work all day. 함수를정의하면,또다른함수내부에서사용이 가능하다.예를들어, 이전후 렴구를반복하기 위해repeat_lyrics함수를 작성할수있다. def repeat_lyrics(): print_lyrics() print_lyrics() 그리고나서,repeat_lyrics함수를호출한다. >>> repeat_lyrics() I'm a lumberjack, and I'm okay. I sleep all night and I work all day. I'm a lumberjack, and I'm okay. I sleep all night and I work all day. 하지만, 이것이실제노래가불려지는 것은아니다. 제 7절 함수정의와사용법 앞 절의 코드 조각을 모아서 작성한 전체 프로그램은 다음과 같다. def print_lyrics(): print "I'm a lumberjack, and I'm okay." print 'I sleep all night and I work all day.' def repeat_lyrics(): print_lyrics() print_lyrics() repeat_lyrics() 상기 프로그램에는 두개의 함수(print_lyrics, repeat_lyrics)가 있다. 함수 정의는다른문장처럼수행되지만,함수 객체를생성한다는점에서차이가 있 다.함수내부문장은함수가호출되기전까지수행되지않고,함수정의는출력 값도생성하지않는다. 예상하듯이,함수를실행하기전에함수를생성해야한다.다시말해서,처음으 로호출되기전에함수정의가실행되어야한다. Exercise 4.2 상기프로그램의마지막줄을최상단으로옮겨서함수정의전에 호출되도록프로그램을고쳐보세요.프로그램을실행서오류메시지를확인하 세요. Exercise 4.3 함수 호출을 맨 마지막으로 옮기고, repeat_lyrics 함수 정의 뒤 에 print_lyrics함수를옮기세요.프로그램을실행하게되면무슨 일이발생 하나요?
67 8. 실행 흐름 49 제 8절 실행흐름 처음으로 함수가 사용되기 전에 정의되었는지를 확인하기 위해서, 명령문 실행 순서를 파악해야 하는데 이를 실행 흐름(flow of execution)이라고 한다. 프로그램실행은항상프로그램첫문장부터시작한다.명령문은한번에하나씩 위에서 아래로 실행된다. 함수정의(definitions)가프로그램실행순서를바꾸지는않는다.하지만,함수 내부의문장은함수가호출될때까지실행이되지않는다는 것을기억하자. 함수호출은프로그램실행흐름을우회하는 것과 같다.다음문장으로 가기 전에,실행흐름은함수몸통부문을실행하고는 건너뛰기를시작한지점으로 다시 돌아온다. 함수가또다른함수를호출한다는 것을기억할때까지는매우 간단하게들린다. 함수중간에서프로그램이또다른함수의문장을수행할지도모른다.하지만, 새로운함수를실행하는중간에프로그램이또다른함수를실행할지도모른다! 다행스럽게도,파이썬은프로그램실행 위치를정확히추적한다.그래서,함수 가실행을완료할때마다,프로그램을함수를호출해서떠난지점으로정확히 되돌려놓는다.프로그램이마지막에도달했을때,프로그램은종료한다. 이렇게복잡한 이야기의교훈은무엇일까요?프로그램을 읽을때, 위에서부터 아래로 읽을필요는없다.때때로,실행흐름을따르는 것이좀더 이치에맞는다. 제 9 절 매개 변수(parameter)와 인수(argument) 지금까지살펴본몇몇내장함수는 인자를요구한다.예를들어, math.sin함 수를호출할때,숫자를 인자로넘겨야한다.어떤함수는 2개 이상의 인수를 받는다.math.pow는밑과지수 2개의 인자가필요하다. 인자는 함수 내부에서 매개 변수(parameters)로 불리는 변수로 대입된다. 하나 의 인자를받는사용자정의함수(user-defined function)가예제로 있다. def print_twice(bruce): print bruce print bruce 사용자정의함수는 인자를받아매개변수 bruce에대입한다.함수가호출될 때,매개변수의 값(무엇이든관계없이)을두번출력합니다. 사용자 정의 함수는 출력 가능한 임의의 값에 작동한다. >>> print_twice('spam') Spam Spam >>> print_twice(17) 17 17
68 50 제 4 장. 함수 >>> print_twice(math.pi) 내장함수에적용되는동일한구성규칙이사용자정의함수에도적용되어서, print_twice함수 인자로표현식어떤종류도 가능하다. >>> print_twice('spam '*4) Spam Spam Spam Spam Spam Spam Spam Spam >>> print_twice(math.cos(math.pi)) 함수가호출되기전에 인자에대한평가는완료되어,예제에서 'Spam '*4과 math.cos(math.pi)은 단지 1회만 평가된다. 변수도 인자로 사용이 가능하다. >>> michael = 'Eric, the half a bee.' >>> print_twice(michael) Eric, the half a bee. Eric, the half a bee. 인수자 넘기는 변수명(michael)은 매개 변수명(bruce)과 아무런 연관이 없다. 무슨 값이호출된든지호출하는 측과상관이없다.여기print_twice함수에서 는 누구나 bruce라고 부르면 된다. 제 10 절 결과있는 함수(fruitful function)와 빈 함수(void function) 수학함수와 같은몇몇함수는 결과를만들어낸다.좀더좋은 이름이없어서, 결과를 만들어 내는 함수를 결과있는 함수(fruitful functions)라고 명명한다. print_twice와 같이액션을수행하지만, 결과를만들어내지않는함수를빈 함수(void functions)라고부른다. 결과있는함수를호출할때는 결과값을 가지고뭔가를하려고한다.예를들어, 결과값을 변수에 대입하거나, 표현식의 일부로 사용할 수 있다. x = math.cos(radians) golden = (math.sqrt(5) + 1) / 2 인터랙티브 모드에서 함수를 호출할 때, 파이썬은 결과를 화면에 출력한다. >>> math.sqrt(5) 하지만, 스크립트에서 결과있는 함수를 호출하고 변수에 결과값을 저장하지 않 으면 반환되는 결과값은 안개속에 사라져간다! math.sqrt(5)
69 11. 왜 함수를 사용하는가? 51 이스크립트는 5의제곱근을 계산하지만,변수에 결과값을저장하거나,화면에 출력하지않아서그다지 유용하지는않다. 빈 함수(Void functions)는 화면에 출력하거나 무엇인가 다른 효과를 가지지만, 반환값이없다.빈함수를사용하여 결과에변수를대입하면, None으로불리는 특별한 값을얻게된다. >>> result = print_twice('bing') Bing Bing >>> print result None None 값은 자신만의 특별한 값을 가지며, 문자열'None' 과는 같지 않다. >>> print type(none) <type 'NoneType'> 함수에서 결과를반환하기 위해서,함수내부에 return문을사용한다.예를들 어,두숫자를더해서 결과를반환하는 addtwo라는 간단한함수를 작성할수 있다. def addtwo(a, b): added = a + b return added x = addtwo(3, 5) print x 상기스크립트가실행될때print문은 8 을출력한다.왜냐하면, 3과 5를 인수 로받는 addtwo함수가호출되기때문이다.함수내부에매개변수 a, b는 각각 3, 5이다. addtwo함수는두숫자덧셈을수행하고 added라는로컬변수에저 장하고, return문을사용해서덧셈 결과를반환하고, x라는변수에대입해서 출력한다. 제 11절 왜함수를사용하는가? 프로그램을함수로나누는 고생을할가치가 있는지명확하지않을수있다. 다음에여기몇가지 이유가 있다. 문장을그룹으로만들어새로운함수로명명하는 것이프로그램을 읽고, 이해하고,디버그하기좋게한다. 함수는반복코드를제거해서프로그램을 작고콤팩트하게만든다.나중 에프로그램에수정사항이생기면,단지한곳에서만수정을하면된다. 긴프로그램을함수로나누어 작성하는 것은 작은부분에서버그를수정 할수있게하고, 이를조합해서전체적으로동작하는프로그램을만들수 있다.
70 52 제 4 장. 함수 잘설계된함수는종종많은프로그램에서 유용하게사용된다. 잘설계 된프로그램을 작성하고디버그를해서오류가없이만들게되면,나중에 재사용도 용이하다. 책의나머지부분에서 이 개념을설명하는함수정의를종종사용한다. "리스 트에서 가장 작은 값을찾아내는 것"과 같이아이디어를적절하게추상화하여 함수를 작성하는 것이함수를만들고사용하는기술의 일부가된다.나중에,리 스트에서 가장 작은 값을찾아내는코드를보여줄것입니다.리스트를 인수로 받아 가장 작은 값을반환하는 min함수를 작성해서여러분에게보여드릴 것 이다. 제 12절 디버깅 텍스트편집기로스크립트를 작성한다면 공백과탭으로몇번씩문제에봉착 했을 것입니다. 이런문제를피하는 가장최선의방식은절대탭을사용하지 말고 공백(스페이스)를사용하는 것이다.파이썬을 인식하는대부분의텍스트 편집기는디폴트로 이런기능을지원하지만,몇몇텍스트편집기는 이런기능을 지원하지않아탭과 공백문제를야기한다. 탭과 공백은통상눈에보이지않기때문에디버그를어렵게한다. 자동으로 들여쓰기를해주는편집기를프로그램 작성시사용한다. 프로그램을실행하기전에저장하는 것을 잊지마세요.몇몇 개발환경은 자동 저장기능을지원하지만그렇지않는 것도 있다. 이런 이유때문에텍스트편집 기에서 작성한 개발 프로그램과 실행운영하고 있는 프로그램이 같지 않을 수도 있다. 동일하고 잘못된프로그램을반복적으로실행한다면,디버깅은오래 걸릴수 있다. 작성하고 있는코드와실행하는코드가 일치하는지필히확인하자.확신을하 지못한다면,프로그램의첫줄에print 'hello' 을넣어서실행해보자.hello 를보지못한다면, 작성하고 있는프로그램과실행하고 있는프로그램은다른 것이다. 제 13절 용어정의 알고리즘(algorithm): 특정 범주의 문제를 해결하는 일반적인 프로세스 인자(argument): 함수가호출될때함수에제공되는 값. 이 값은함수내부에 상응하는 매개 변수에 대입된다. 몸통 부문(body): 함수 정의 내부에 일련의 문장 구성(composition): 좀더 큰 표현식의 일부분으로 표현식을 사용하거나, 좀더 큰문장의 일부로서의문장
71 14. 연습문제 53 결정론적(deterministic): 동일한 입력값이 주어지고 실행될 때마다 동일한 행 동을하는프로그램에관련된 것. 점 표기법(dot notation): 점과 함수명으로 모듈명을 명세함으로써 다른 모듈의 함수를호출하는구문. 실행 흐름(flow of execution): 프로그램 실행 동안 명령문이 실행되는 순서. 결과있는 함수(fruitful function): 반환값을 가지는 함수. 함수(function): 유용한연산을수행하는 이름을 가진 일련의명령문.함수는 인수를 가질수도 갖지않을수도 있고, 결과값을생성할수도생성하지 않을수도 있다. 함수 호출(function call): 함수를 실행하는 명령문. 함수 이름과 인자 리스트로 구성된다. 함수 정의(function definition): 신규 함수를 정의하는 명령문으로 이름, 매개 변수,실행명령문을명세한다. 함수 객체(function object): 함수 정의로 생성되는 값. 함수명은 함수 객체를 참조하는 변수다. 머리 부문(header): 함수 정의의 첫번째 줄 가져오기 문(import statement): 모듈 파일을 읽어 모듈 개체를 생성하는 명령 문 모듈 개체(module object): import문에 의해서 생성된 모듈에 정의된 코드와 데이터에접근할수있는 값 매개변수(parameter): 인자로전달된 값을참조하기 위해함수내부에사용되 는 이름 의사 난수(pseudorandom): 난수처럼 보이는 일련의 숫자와 관련되어 있지만, 결정론적 프로그램에 의해 생성된다. 반환 값(return value): 함수의 결과. 함수 호출이 표현식으로 사용된다면, 반환 값은표현식의 값이된다. 빈 함수(void function): 반환값을 갖지 않는 함수 제 14절 연습문제 Exercise 4.4 파이썬 "def"키워드의목적은무엇입니까? a) "다음의코드는정말좋다"라는 의미를가진속어 b)함수의시작을표시한다. c)다음의들여쓰기코드부문은나중을 위해저장되야된다는것을표시한다. d) b와 c모두사실 e) 위모두거짓
72 54 제 4 장. 함수 Exercise 4.5 다음파이썬프로그램은무엇을출력할까요? def fred(): print "Zap" def jane(): print "ABC" jane() fred() jane() a) Zap ABC jane fred jane b) Zap ABC Zap c) ABC Zap jane d) ABC Zap ABC e) Zap Zap Zap Exercise 4.6 프로그램 작성 시 (hours과 rate)을 매개 변수로 갖는 함수 computepay을 생성하여, 초과근무에 대해서는 50% 초과 근무수당을 지급하는 봉급 계산 프로그램을 다시 작성하세요. Enter Hours: 45 Enter Rate: 10 Pay: Exercise 4.7 매개 변수로 점수를 받아 문자열로 등급을 반환하는 computegrade 함수를 사용하여 앞장의 등급 프로그램을 다시 작성하세요. Score Grade > 0.9 A > 0.8 B > 0.7 C > 0.6 D <= 0.6 F Program Execution: Enter score: 0.95 A Enter score: perfect Bad score Enter score: 10.0 Bad score Enter score: 0.75 C
73 14. 연습문제 55 Enter score: 0.5 F 반복적으로 프로그램을 실행해서 다양한 다른 입력값을 테스트해 보세요.
74 56 제 4 장. 함수
75 제 5 장 반복(Iteration) 제 1절 변수 갱신 대입문의흔한패턴은변수를 갱신하는대입문이다.변수의새로운 값은 이전 값에 의존한다. x = x+1 상기예제는 현재 값x에 1을더해서x를새로운 값으로 갱신한다. 만약존재하지않는변수를 갱신하면,오류가발생한다.왜냐하면 x에 값을대 입하기 전에 파이썬이 오른쪽을 먼저 평가하기 때문이다. >>> x = x+1 NameError: name 'x' is not defined 변수를 갱신하기전에 간단한변수대입으로통상먼저초기화(initialize)한다. >>> x = 0 >>> x = x+1 1을더해서변수를 갱신하는 것을증가(increment)라고하고, 1을빼서변수를 갱신하는 것을 감소(decrement)라고한다. 제 2절 while문 종종반복적인 작업을 자동화하기 위해서 컴퓨터를사용한다.오류없이동일 하거나비슷한 작업을반복하는 일은 컴퓨터가사람보다 잘한다.반복이매우 흔한 일이어서,파이썬에서반복 작업을쉽게하도록몇가지언어적기능을제 공한다. 파이썬에서반복의한형태가 while문이다.다음은 5에서부터 거꾸로세어서 마지막에 Blastoff(발사)! 를 출력하는 간단한 프로그램이다.
76 58 제 5 장. 반복(Iteration) n = 5 while n > 0: print n n = n-1 print 'Blastoff(발사)!' 마치영어를 읽듯이 while을 읽어내려갈수있다. n이 0보다큰동안에 n의 값을출력하고 n 값에서 1만큼뺀다. 0에도달했을때, while문을빠져나가 Blastoff(발사)! 를 화면에 출력한다. 좀더형식을 갖춰정리하면,다음이while문에대한실행흐름에대한정리다. 1. 조건을 평가해서 참(True) 혹은 거짓(False)를 산출한다. 2. 만약조건이 거짓이면,while문을빠져나가다음문장을 계속실행한다. 3. 만약조건이참이면,몸통부문의문장을실행하고다시처음 1번단계로 돌아간다. 3번째단계에서처음으로다시돌아가는반복을하기때문에 이런종류의흐름 을루프(loop)이라고부른다.매번루프몸통부문을실행할때마다, 이것을반복 (iteration)이라고한다.상기루프에대해서 5번반복했다 고말한다.즉,루프 몸통 부문이 5번 수행되었다는 의미가 된다. 루프몸통부문은필히하나혹은그이상의변수값을바꾸어서종국에는조건 식이 거짓(false)이되어루프가종료되게만들어야한다.매번루프가실행될때 마다상태를변경하고언제루프가끝날지제어하는변수를반복변수(iteration variable)라고한다.만약반복변수가없다면,루프는영원히반복될 것이고, 결국 무한 루프(infinite loop)에 빠질 것이다. 제 3절 무한루프 프로그래머에게무한한즐거움의원천은아마도 "거품내고,헹구고,반복" 이 렇게적혀있는샴프사용법문구가무한루프라는 것을알아차릴때일 것이다. 왜냐하면,얼마나많이루프를실행해야하는지말해주는반복변수(iteration variable)가 없어서 무한 반복하기 때문입니다. 숫자를꺼꾸로세는 (countdown)예제는루프가끝나는 것을증명할수있다. 왜냐하면 n값이 유한하고, n이매번루프를돌때마다 작아져서 결국 0에도달 할 것이기때문이다.다른 경우반복변수가전혀없어서루프가명백하게무한 반복한다. 제 4절 무한반복과break 가끔몸통부문을절반진행할때까지루프를종료해야하는시점인지확신하 지못한다. 이런 경우 의도적으로무한루프를 작성하고 break문을사용하여 루프를빠져나온다.
77 4. 무한반복과break 59 다음루프는명백하게무한루프(infinite loop)가되는데 이유는 while문논리 표현식이단순히논리상수참(True)으로되어 있기때문이다. n = 10 while True: print n, n = n - 1 print 'Done!' 실수하여 상기 프로그램을 실행한다면, 폭주하는 파이썬 프로세스를 어떻게 멈 추는지빨리배우거나, 컴퓨터의전원버튼이어디에 있는지찾아야할것이다. 표현식상수 값이참(True)이라는사실로루프상단논리연산식이항상참값 이여서 프로그램이 영원히 혹은 배터리가 모두 소진될 때까지 실행된다. 이것이역기능무한루프라는 것은사실이지만, 유용한루프를 작성하기 위해 는 이패턴을여전히 이용할 것이다. 이를 위해서루프몸통부문에 break문을 사용하여 루프를 빠져나가는 조건에 도달했을 때, 루프를 명시적으로 빠져나갈 수 있도록주의깊게코드를추가해야한다. 예를들어,사용자가done을 입력하기전까지사용자로부터 입력값을받는다고 가정해서 프로그램 코드를 다음과 같이 작성한다. while True: line = raw_input('> ') if line == 'done': break print line print 'Done!' 루프조건이항상참(True)이여서 break문이호출될때까지루프는반복적으 로실행된다. 매번프로그램이꺾쇠괄호로사용자에게명령문을받을준비를한다.사용자가 done을타이핑하면,break문이실행되어루프를빠져나온다.그렇지않은 경우 프로그램은사용자가무엇을 입력하든메아리처럼 입력한 것을그대로출력하 고다시루프처음으로되돌아 간다.다음예제로실행한 결과가 있다. > hello there hello there > finished finished > done Done! while루프를 이와 같은방식으로 작성하는 것이흔한데프로그램상단에서 뿐만아니라루프어디에서나조건을확인할수있고피동적으로 이벤트가발 생할때까지 계속실행"대신에,적극적으로 이벤트가생겼을때중지 로멈춤 조건을표현할수있다.
78 60 제 5 장. 반복(Iteration) 제 5절 continue로반복종료 때때로루프를반복하는중간에서현재반복을끝내고,다음반복으로즉시점 프하여 이동하고싶을때가 있다.현재반복루프몸통부분전체를끝내지않고 다음 반복으로 건너뛰기 위해서 continue문을 사용한다. 사용자가 done 을 입력할때까지 입력값을그대로복사하여출력하는루프 예제가 있다.하지만파이썬주석문처럼해쉬(#)로시작하는줄은출력하지않 느다. while True: line = raw_input('> ') if line[0] == '#' : continue if line == 'done': break print line print 'Done!' continue문이 추가된 새로운 프로그램을 샘플로 실행했다. > hello there hello there > # don't print this > print this! print this! > done Done! 해쉬 기호(#)로 시작하는 줄을 제외하고 모든 줄을 출력한다. 왜냐하면, continue문이실행될때,현재반복을종료하고while문처음으로돌아가서다 음반복을실행하게되어서print문을 건너뛴다. 제 6절 for문을사용한명확한루프 때때로,단어리스트나,파일의줄,숫자리스트 같은사물의집합에대해루프 를반복할때가 있다.루프를반복할사물리스트가 있을때, for문을사용해서 확정 루프(definite loop)를 구성한다. while문을 불확정 루프(indefinite loop)라고 하는데, 왜냐하면 어떤 조건이 거짓 (False)가 될 때까지 루프가 단순히 계혹해서 돌기 때문이다. 하지만, for루프 는확정된항목의집합에대해서루프가돌게되어서집합에 있는항목만큼만 실행이된다. for문이 있고,루프몸통부문으로구성된다는점에서 for루프구문은 while 루프구문과비슷하다. friends = ['Joseph', 'Glenn', 'Sally'] for friend in friends: print 'Happy New Year:', friend print 'Done!'
79 7. 루프 패턴 61 파이썬용어로,변수 friends는 3개의문자열을 가지는리스트고, for루프는 리스트를하나씩하나씩찾아서리스트에 있는 3개문자열 각각에대해출력을 실행하여다음 결과를얻게된다. Happy New Year: Joseph Happy New Year: Glenn Happy New Year: Sally Done! for루프를영어로번역하는 것이while문을번역하는 것과 같이직접적이지는 않다.하지만,만약friends를집합(set)으로생각한다면다음과 같다.friends 라고명명된집합에서friend 각각에대해서한번씩for루프몸통부문에 있는 문장을실행하라. for 루프를 살펴보면, for와 in은 파이썬 예약어이고 friend와 friends는 변수 이다. for friend in friends: print Happy New Year, friend 특히, friend는 for 루프의 반복 변수(iteration variable)다. 변수 friend는 루 프가매번반복할때마다변하고,언제 for루프가완료되는지제어한다.반복 변수는 friend 변수에 저장된 3개 문자열을 순차적으로 훑고 간다. 제 7절 루프패턴 종종 for문과 while문을사용하여,리스트항목,파일콘텐츠를훑어 자료에 있는 가장큰값이나 작은 값 같은 것을찾는다. for나 while 루프는 일반적으로 다음과 같이 구축된다. 루프가시작하기전에하나혹은그이상의변수를초기화 루프몸통부분에 각항목에대해연산을수행하고,루프몸통부분의변수 상태를변경 루프가완료되면 결과변수의상태확인 루프패턴의 개념과 작성을시연하기 위해서숫자리스트를사용한다. 7.1 계수(counting)와 합산 루프 예를들어,리스트의항목을세기 위해서다음과 같이for루프를 작성한다. count = 0 for itervar in [3, 41, 12, 9, 74, 15]: count = count + 1 print 'Count: ', count
80 62 제 5 장. 반복(Iteration) 루프가시작하기전에변수 count를 0 으로설정하고,숫자목록을훑어 갈 for 루프를 작성한다. 반복(iteration) 변수는 itervar라고 하고, 루프에서 itervar 을사용되지않지만, itervar는루프를제어하고루프몸통부문리스트의 각 값에대해서한번만실행되게한다. 루프몸통부문에리스트의 각 값에대해서변수count 값에 1을더한다.루프가 실행될때,count 값은 지금까지 살펴본 값의횟수가된다. 루프가종료되면, count 값은총항목숫자가된다.총숫자는루프맨마지막에 얻어진다.루프를구성해서,루프가끝났을때기대했던바를얻었다. 숫자집합의 갯수를세는또다른비슷한루프는다음과 같다. total = 0 for itervar in [3, 41, 12, 9, 74, 15]: total = total + itervar print 'Total: ', total 상기 루프에서, 반복 변수(iteration variable)가 사용되었다. 앞선 루프에서처럼 변수 count에 1을 단순히 더하는 대신에, 각 루프가 반복을 수행하는 동안 실제 숫자 (3, 41, 12,등)를 작업중인합계에덧셈을했다.변수 total을생각해보면, total은 지금까지 값의총계다. 루프가시작하기전에 total은어떤 값도살 펴본적이없어서 0 이다.루프가도는중에는 total은 작업중인총계가된다. 루프의 마지막 단계에서 total은 리스트에 있는 모든 값의 총계가 된다. 루프가실행됨에따라, total은 각요소의합계로누적된다. 이방식으로사용 되는 변수를 누산기(accumulator)라고 한다. 계수(counting)루프나합산루프는특히실무에서 유용하지는않다.왜냐하면 리스트에서항목의 개수와총계를 계산하는len()과sum()가 각각내장함수로 있기 때문이다. 7.2 최대값과최소값루프 리스트나열(sequence)에서 가장큰값을찾기 위해서,다음과 같이루프를 작 성한다. largest = None print 'Before:', largest for itervar in [3, 41, 12, 9, 74, 15]: if largest is None or itervar > largest : largest = itervar print 'Loop:', itervar, largest print 'Largest:', largest 프로그램을실행하면,출력은다음과 같다. Before: None Loop: 3 3 Loop: Loop: 12 41
81 7. 루프 패턴 63 Loop: 9 41 Loop: Loop: Largest: 74 변수 largest는 지금까지본가장큰수"로생각할수있다.루프시작전에 largest 값은 상수 None이다. None은 빈(empty) 변수를 표기하기 위해서 변 수에저장하는특별한상수 값이다. 루프시작전에지금까지본가장큰수는 None이다.왜냐하면아직어떤 값도 보지않았기때문이다.루프가실행되는동안에,largest 값이None이면,첫번 째본값이지금까지본가장큰값이된다.첫번째반복에서 itervar는 3 이 되는데largest 값이None이여서즉시,largest값을 3 으로 갱신한다. 첫번째 반복 후에 largest는 더 이상 None이 아니다. itervar > largest인 지를확인하는복합논리표현식의두번째부분은 지금까지본 값보다더 큰 값을찾게될때자동으로동작한다. 심지어더큰 값을찾게되면변수 largest에새로운 값으로대체한다. largest가 3에서 41, 41에서 74로변경되 어출력되어나가는 것을확인할수있다. 루프의끝에서모든 값을훑어서변수 largest는리스트의 가장큰값을담고 있다. 최소값을 계산하기 위해서는코드가매우 유사하지만 작은변화가 있다. smallest = None print 'Before:', smallest for itervar in [3, 41, 12, 9, 74, 15]: if smallest is None or itervar < smallest: smallest = itervar print 'Loop:', itervar, smallest print 'Smallest:', smallest 변수 smallest는루프실행전에,중에,완료후에 지금까지본가장 작은" 값이된다.루프실행이완료되면,smallest는리스트의최소 값을담게된다. 계수(counting)과 합산에서와 마찬가지로 파이썬 내장함수 max()와 min()은 이런루프문 작성을불필요하게만든다. 다음은파이썬내장min()함수의 간략버전이다. def min(values): smallest = None for value in values: if smallest is None or value < smallest: smallest = value return smallest 가장적은코드로 작성한함수버전은파이썬에 이미내장된min함수와동등하 게 만들기 위해서 모든 print문을 삭제했다.
82 64 제 5 장. 반복(Iteration) 제 8절 디버깅 좀더큰프로그램을 작성할때,좀더많은시간을디버깅에보내는 자신을발 견할 것이다.좀더많은코드는버그가숨을수있는좀더많은 장소와오류가 발생할기회가 있다는 것을 의미한다. 디버깅시간을줄이는한방법은 이분법에따라디버깅(debugging by bisection) 하는 것이다.예를들어,프로그램에 100줄이 있고한번에하나씩확인 한다면, 100번단계가필요하다. 대신에문제를반으로나눈다.프로그램정확히중간이나,중간부분에서점검 한다.print문이나, 검증효과를 갖는상응하는대용물을넣고프로그램을실행 한다. 중간지점점검 결과 잘못되었다면문제는양분한프로그램앞부분에틀림없이 있다. 만약 정확하다면, 문제는 프로그램 뒷부분에 있다. 이와 같은방식으로점검하게되면, 검토해야하는코드의줄수를절반으로 계 속줄일수있다.단계가 100번걸리는 것에비해 6번단계후에 이론적으로 1 혹은 2줄로문제코드의범위를좁힐수있다. 실무에서, 프로그램의중간 이무엇인지는명확하지않고,확인하는 것도 가 능하지않다.프로그램코드라인을세서정확히 가운데를찾는 것은 의미가 없다.대신에프로그램오류가생길수있는 곳과오류를확인하기쉬운 장소를 생각하세요.점검지점앞뒤로버그가 있을 곳과동일하게생각하는 곳을중간 지점으로 고르세요. 제 9절 용어정의 누산기(accumulator): 더하거나 결과를 누적하기 위해 루프에서 사용되는 변 수 계수(counter): 루프에서어떤 것이 일어나는횟수를기록하는데사용되는변 수. 카운터를 0 으로초기화하고,어떤 것의 횟수 를셀때카운터를증 가시킨다. 감소(decrement): 변수 값을 감소하여 갱신 초기화(initialize): 갱신될 변수의 값을 초기 값으로 대입 증가(increment): 변수 값을 증가시켜 갱신 (통상 1씩) 무한루프(infinite loop): 종료조건이 결코만족되지않거나종료조건이없는 루프 반복(iteration): 재귀함수 호출이나 루프를 사용하여 명령문을 반복 실행
83 10. 연습문제 65 제 10절 연습문제 Exercise 5.1 사용자가 done 을 입력할때까지반복적으로숫자를 읽는프로 그램을 작성하세요. done 이 입력되면,총계,갯수,평균을출력하세요.만약 숫자가아닌다른것을 입력하게되면,try와except를사용하여사용자실수를 탐지해서오류메시지를출력하고다음숫자로건너뛰게하세요. Enter a number: 4 Enter a number: 5 Enter a number: bad data Invalid input Enter a number: 7 Enter a number: done Exercise 5.2 위에서처럼숫자목록을사용자로부터 입력받는프로그램을 작성 하세요. 평균값 대신에 숫자 목록 최대값과 최소값을 출력하세요.
84 66 제 5 장. 반복(Iteration)
85 제 6 장 문자열 제 1절 문자열은순서(sequence)다. 문자열은여러문자들의순서다.꺾쇠연산자로한번에하나씩문자에접근 한다. >>> fruit = 'banana' >>> letter = fruit[1] 두번째문장은변수fruit에서 1번 위치문자를추출하여변수letter에대입 한다. 꺾쇠 표현식을 인덱스(index)라고 부른다. 인덱스는 순서(sequence)에서 사용자가 어떤 문자를 원하는지 표시한다. 하지만,여러분이기대한 것은아니다. >>> print letter a 대부분의사람에게 'banana'의첫분자는 a가아니라 b다.하지만,파이썬 인 텍스는문자열처음부터오프셋(offset) 1 이다.첫글자오프셋은 0 이다. >>> letter = fruit[0] >>> print letter b 그래서, b가 'banana'의 0번째문자가되고 a가첫번째, n이두번째문자가 된다. b a n a n a [0] [1] [2] [3] [4] [5] 인덱스로문자와연산자를포함하는어떤표현식도사용가능지만, 인덱스 값은 정수여야만한다.정수가아닌 경우다음과 같은 결과를얻게된다. 1 컴퓨터에서어떤주소로부터간격을두고떨어진주소와의거리.기억 장치가페이지혹은 세그먼트단위로나누어져 있을때하나의시작주소로부터오프셋만큼떨어진 위치를나타내는 것이다. [네이버지식백과]오프셋 [offset] (IT용어사전,한국정보통신기술협회)
86 68 제 6 장. 문자열 >>> letter = fruit[1.5] TypeError: string indices must be integers 제 2절 len함수사용문자열길이구하기 len 함수는 문자열의 문자 갯수를 반환하는 내장함수다. >>> fruit = 'banana' >>> len(fruit) 6 문자열의 가장마지막문자를얻기 위해서,아래와 같이시도하려싶을 것이다. >>> length = len(fruit) >>> last = fruit[length] IndexError: string index out of range 인덱스 오류 (IndexError) 이유는 banana 에6번 인텍스문자가없기때문 이다. 0에서부터시작했기때문에 6개문자는 0에서부터 5까지번호가매겨졌 다.마지막문자를얻기 위해서length에서 1을빼야한다. >>> last = fruit[length-1] >>> print last a 대안으로 음의 인텍스를사용해서문자열끝에서역으로수를셀수있다.표현 식 fruit[-1]은마지막문자를 fruit[-2]는끝에서두번째등등활용할수 있다. 제 3절 루프를사용한문자열운행법 연산의많은 경우에문자열을한번에한문자씩처리한다.종종처음에서시작 해서,차례로 각문자를선택하고,선택된문자에 임의연산을수행하고,끝까지 계속한다. 이런처리패턴을운행법(traversal)라고한다.운행법을 작성하는한 방법이while루프다. index = 0 while index < len(fruit): letter = fruit[index] print letter index = index + 1 while 루프가 문자열을 운행하여 문자열을 한줄에 한 글자씩 화면에 출력한다. 루프 조건이 index < len(fruit)이여서, index가 문자열 길이와 같을 때, 조 건은 거짓이되고,루프의몸통부문은실행이되지않는다.파이썬이접근한 마지막 len(fruit)-1 인텍스 문자로, 문자열의 마지막 문자다. Exercise 6.1 문자열의마지막문자에서시작해서,문자열처음으로역진행하 면서한줄에한자씩화면에출력하는while루프를 작성하세요.
87 4. 문자열 슬라이스(slice) 69 운행법을 작성하는 또 다른 방법은 for 루프다. for char in fruit: print char 루프를매번반복할때,문자열다음문자가변수 char에대입된다.루프는더 이상남겨진문자가없을때까지 계속실행된다. 제 4절 문자열슬라이스(slice) 문자열의 일부분을 슬라이스(slice)라고 한다. 문자열 슬라이스를 선택하는 것 은문자를선택하는 것과 유사하다. >>> s = 'Monty Python' >>> print s[0:5] Monty >>> print s[6:13] Python [n:m]연산자는 n번째문자부터 m번째문자까지의문자열 -첫번째는포함하 지만마지막은제외 -부분을반환한다. 콜론앞첫인텍스를생략하면,문자열슬라이스는문자열처음부터시작한다. 두번째 인텍스를생략하면,문자열슬라이스는문자열끝까지 간다. >>> fruit = 'banana' >>> fruit[:3] 'ban' >>> fruit[3:] 'ana' 만약첫번째 인텍스가두번째보다크거나 같은 경우 결과는 인용부호로표현되 는빈문자열(empty string)이된다. >>> fruit = 'banana' >>> fruit[3:3] '' 빈문자열은어떤문자도포함하지않아서길이가 0 이되지만, 이것을제외하고 다른문자열과동일하다. Exercise 6.2 fruit이문자열로주어졌을때,fruit[:]의 의미는무엇인가요? 제 5절 문자열은불변이다. 문자열내부에 있는문자를변경하려고대입문왼쪽편에[]연산자를사용하고 싶은 유혹이 있을 것이다.예를들어다음과 같다. >>> greeting = 'Hello, world!' >>> greeting[0] = 'J' TypeError: object does not support item assignment
88 70 제 6 장. 문자열 이 경우 객체(object) 는 문자열이고, 대입하고자 하는 문자는 항목(item) 이다.지금으로서 객체는 값과동일하지만,나중에 객체정의를좀더상세화할 것이다.항목은순서 값중의하나다. 오류 이유는 문자열은 불변(immutable)이기 때문이다. 따라서 기존 문자열을 변경할수없다는 의미다.최선의방법은원래문자열을변형한새로운문자열 을생성하는 것이다. >>> greeting = 'Hello, world!' >>> new_greeting = 'J' + greeting[1:] >>> print new_greeting Jello, world! 새로운첫문자에 greeting문자열슬라이스를연결한다.원래문자열에는어 떤영향도주지않는새로운문자열을생성되었다. 제 6 절 루프 돌기(looping) 계수(counting) 다음프로그램은문자열에문자a가나타나는횟수를 계수한다. word = 'banana' count = 0 for letter in word: if letter == 'a': count = count + 1 print count 상기 프로그램은 계수기(counter)라고 부르는 또다른 연산 패턴을 보여준다. 변수count는 0 으로초기화되고,매번a를찾을때마다증가한다.루프를빠져 나갔을때,count는 결과 값즉,a가나타난총횟수를담고 있다. Exercise 6.3 문자열과 문자를 인자(argument)로 받도록 상기 코드를 count라 는 함수로 캡슐화(encapsulation)하고 일반화하세요. 제 7절 in연산자 연산자 in 은불연산자로두개의문자열을받아,첫번째문자열이두번째 문자열의 일부이면참(True)을반환한다. >>> 'a' in 'banana' True >>> 'seed' in 'banana' False 제 8절 문자열비교 비교 연산자도 문자열에서 동작한다. 두 문자열이 같은지를 살펴보다.
89 9. string 메쏘드 71 if word == 'banana': print 'All right, bananas.' 다른비교연산자는단어를알파벳순서로정렬하는데 유용하다. if word < 'banana': print 'Your word,' + word + ', comes before banana.' elif word > 'banana': print 'Your word,' + word + ', comes after banana.' else: print 'All right, bananas.' 파이썬은사람과동일하는방식으로대문자와소문자를다루지않는다.모든 대문자는 소문자 앞에 온다. Your word, Pineapple, comes before banana. 이러한문제를다루는 일반적인방식은비교연산을수행하기전에문자열 을표준포맷으로예를들어모두소문자,변환하는 것입니다. 경우에따라서 Pineapple 로 무장한 사람들로부터 여러분을 보호해야하는 것을 명심하세요. 제 9절 string메쏘드 문자열은파이썬 객체(objects)의한예다. 객체는데이터(실제문자열 자체)와 메쏘드(methods)를담고 있다.메쏘드는 객체에내장되고어떤 객체의 인스턴 스(instance)에도 사용되는 사실상 함수다. 객체에대해 이용가능한메쏘드를보여주는dir함수가파이썬에 있다.type함 수는 객체의 자료형(type)을보여주고, dir은 객체에사용될수있는메쏘드를 보여준다. >>> stuff = 'Hello world' >>> type(stuff) <type 'str'> >>> dir(stuff) ['capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'] >>> help(str.capitalize) Help on method_descriptor: capitalize(...) S.capitalize() -> string >>> Return a copy of the string S with only its first character capitalized.
90 72 제 6 장. 문자열 dir함수가메쏘드목록을보여주고,메쏘드에대한 간단한문서정보는 help 를사용할수있지만,문자열메쏘드에대한좀더좋은문서정보는 docs. python.org/library/string.html에서 찾을 수 있다. 인자를받고 값을반환한다는점에서메쏘드(method)를호출하는 것은함수를 호출하는 것과 유사하지만,구문은다르다.구분자로점을사용해서변수명에 메쏘드명을 붙여 메쏘드를 호출한다. 예를들어,upper메쏘드는문자열을받아모두대문자로변환된새로운문자열 을반환한다. 함수 구문 upper(word) 대신에, word.upper() 메쏘드 구문을 사용한다. >>> word = 'banana' >>> new_word = word.upper() >>> print new_word BANANA 이런형태의점표기법은메쏘드 이름(upper)과메쏘드가적용되는문자열 이름 (word)을명세한다.빈괄호는메쏘드가 인자가없다는 것을나타낸다. 메쏘드를 부르는 것을 호출(invocation)이라고 부른다. 상기의 경우, word에 upper 메쏘드를 호출한다고 말한다. 예를 들어, 문자열안에 문자열의 위치를 찾는 find라는 문자열 메쏘드가 있다. >>> word = 'banana' >>> index = word.find('a') >>> print index 1 상기 예제에서, word 문자열의 find 메쏘드를 호출하여 매개 변수로 찾고자 하 는문자를넘긴다. find 메쏘드는 문자뿐만 아니라 부속 문자열(substring)도 찾을 수 있다. >>> word.find('na') 2 두번째 인자로어디서 검색을시작할지 인텍스를넣을수있다. >>> word.find('na', 3) 4 한 가지 자주 있는 작업은 strip메쏘드를사용해서문자열시작과끝의 공백 (공백여러개,탭,새줄)을제거하는 것이다. >>> line = ' Here we go ' >>> line.strip() 'Here we go' startswith메쏘드는참, 거짓 같은불값(boolean value)을반환한다.
91 10. 문자열 파싱(Parsing) 73 >>> line = 'Please have a nice day' >>> line.startswith('please') True >>> line.startswith('p') False startswith가대소문자를구별하는 것을요구하기때문에 lower메쏘드를사 용해서 검증을수행하기전에,한줄을 입력받아모두소문자로변환하는 것이 필요하다. >>> line = 'Please have a nice day' >>> line.startswith('p') False >>> line.lower() 'please have a nice day' >>> line.lower().startswith('p') True 마지막예제에서문자열이문자 p 로시작하는지를 검증하기 위해서, lower 메쏘드를호출하고나서바로startswith메쏘드를사용한다.주의깊게순서만 다룬다면,한줄에다수메쏘드를호출할수있다. Exercise 6.4 앞선예제와 유사한함수인 count로불리는문자열메쏘드가 있 다. docs.python.org/library/string.html에서 count 메쏘드에 대한 문서 를 읽고,문자열'banana'의문자가몇개인지계수하는메쏘드호출프로그램 을 작성하세요. 제 10 절 문자열 파싱(Parsing) 종종,문자열을들여다보고특정부속문자열(substring)을찾고싶다.예를들 어,아래와 같은형식으로 작성된 일련의라인이주어졌다고 가정하면, From stephen.marquard@ uct.ac.za Sat Jan 5 09:14: 각라인마다뒤쪽전자우편주소(즉,uct.ac.za)만뽑아내고싶을 것이다.find 메쏘드와 문자열 슬라이싱(string sliceing)을 사용해서 작업을 수행할 수 있다. 우선,문자열에서 골뱅이(@, at-sign)기호의 위치를찾는다.그리고, 골뱅이기 호뒤첫 공백 위치를찾는다.그리고나서,찾고자하는부속문자열을뽑아내기 위해서 문자열 슬라이싱을 사용한다. >>> data = 'From stephen.marquard@uct.ac.za Sat Jan 5 09:14: ' >>> atpos = data.find('@') >>> print atpos 21 >>> sppos = data.find(' ',atpos) >>> print sppos 31 >>> host = data[atpos+1:sppos] >>> print host uct.ac.za >>>
92 74 제 6 장. 문자열 find메쏘드를사용해서찾고자하는문자열의시작 위치를명세한다.문자열 슬라이싱(slicing)할 때, 골뱅기 기호 뒤부터 빈 공백을 포함하지 않는 위치까지 문자열을뽑아낸다. find 메쏘드에 대한 문서는 docs.python.org/library/string.html 에서참조 가능하다. 제 11절 서식연산자 서식연산자(format operator), %는문자열 일부를변수에저장된 값으로바꿔 문자열을구성한다.정수에서식연산자가적용될때, %는나머지연산자가된 다.하지만첫피연산자가문자열이면,%은서식연산자가된다. 첫피연산자는서식문자열 format string로두번째피연산자가어떤형식으로 표현되는지를명세하는하나혹은그이상의서식순서 format sequence를담고 있다. 결과값은문자열이다. 예를들어,형식순서'%d'의 의미는두번째피연산자가정수형식으로표현됨 을뜻한다. (d는 decimal 을나타낸다.) >>> camels = 42 >>> '%d' % camels '42' 결과는문자열'42'로정수42와혼동하면안된다. 서식순서는문자열어디에도나타날수있어서문장중간에 값을 임베드(embed)할수있다. >>> camels = 42 >>> 'I have spotted %d camels.' % camels 'I have spotted 42 camels.' 만약문자열서식순서가하나 이상이라면,두번째 인자는튜플(tuple)이된다. 서식순서 각각은순서대로튜플요소와매칭된다. 다음 예제는 정수 형식을 표현하기 위해서'%d', 부동 소수점 형식을 표현하기 위해서 '%g',문자열형식을표현하기 위해서 '%s'을사용한사례다.여기서 왜 부동 소수점 형식이'%f'대신에'%g'인지는 질문하지 말아주세요. >>> 'In %d years I have spotted %g %s.' % (3, 0.1, 'camels') 'In 3 years I have spotted 0.1 camels.' 튜플요소숫자는문자열서식순서의숫자와 일치해야하고,요소의 자료형 (type)도서식순서와 일치해야한다. >>> '%d %d %d' % (1, 2) TypeError: not enough arguments for format string >>> '%d' % 'dollars' TypeError: illegal argument type for built-in operation
93 12. 디버깅 75 상기첫예제는충분한요소 개수가되지않고,두번째예제는 자료형이맞지 않는다. 서식 연산자는 강력하지만, 사용하기가 어럽다. 더 많은 정보는 docs. python.org/lib/typesseq-strings.html에서 찾을 수 있다. 제 12절 디버깅 프로그램을 작성하면서 배양해야 하는 기술은 항상 자신에게 질문을 하는 것이 다. 여기서 무엇이 잘못 될 수 있을까? 혹은 내가 작성한 완벽한 프로그램을 망가뜨리기 위해사용자는무슨엄청난 일을할것인가?" 예를들어앞장의반복while루프를시연하기 위해사용한프로그램을살펴봅 시다. while True: line = raw_input('> ') if line[0] == '#' : continue if line == 'done': break print line print 'Done!' 사용자가 입력값으로빈공백줄을 입력하게될때무엇이발생하는지살펴봅 시다. > hello there hello there > # don't print this > print this! print this! > Traceback (most recent call last): File "copytildone.py", line 3, in <module> if line[0] == '#' : 빈 공백줄이 입력될때까지코드는 잘 작동합니다.그리고나서, 0번째문자가 없어서 트레이스백(traceback)이 발생한다. 입력줄이 비어있을 때, 코드 3번째 줄을 안전 하게만드는두가지방법이 있다. 하나는 빈 문자열이면 거짓(False)을 반환하도록 startswith 메쏘드를 사용 하는 것이다. if line.startswith('#') : 가디언 패턴(guardian pattern)을 사용한 if문으로 문자열에 적어도 하나의 문 자가 있는 경우만두번째논리표현식이평가되도록코드를 작성한다. if len(line) > 0 and line[0] == '#' :
94 76 제 6 장. 문자열 제 13절 용어정의 계수기(counter): 무언가를 계수하기 위해서 사용되는 변수로 일반적으로 0 으 로 초기화하고 나서 증가한다. 빈문자열(empty string): 두 인용부호로표현되고,어떤문자도없고길이가 0 인문자열. 서식 연산자(format operator): 서식 문자열과 튜플을 받아, 서식 문자열에 지 정된서식으로튜플요소를포함하는문자열을생성하는연산자,%. 서식 순서(format sequence): %d처럼 어떤 값의 서식으로 표현되어야 하는지를 명세하는 서식문자열 문자순서. 서식문자열(format string): 서식순서를포함하는서식연산자와함께사용되 는문자열. 플래그(flag): 조건이 참인지를 표기하기 위해 사용하는 불 변수(boolean variable) 호출(invocation): 메쏘드를 호출하는 명령문. 불변(immutable): 순서의 항목에 대입할 수 없는 특성. 인덱스(index): 문자열의 문자처럼 순서(sequence)에 항목을 선택하기 위해 사 용되는정수 값. 항목(item): 순서에 있는 값의 하나. 메쏘드(method): 객체와 연관되어 점 표기법을 사용하여 호출되는 함수. 객체(object): 변수가참조하는무엇.지금은 객체 와 값 을구별없이사용한 다. 검색(search): 찾고자 하는 것을 찾았을 때 멈추는 운행법 패턴. 순서(sequence): 정돈된집합.즉,정수 인텍스로 각각의 값이확인되는 값의 집합. 슬라이스(slice): 인텍스 범위로 지정되는 문자열 부분. 운행법(traverse): 순서(sequence)의 항목을 반복적으로 훑기, 각각에 대해서는 동일한연산을수행. 제 14절 연습문제 Exercise 6.5 다음문자열을파이썬코드를 작성하세요. str = 'X-DSPAM-Confidence: '
95 14. 연습문제 77 find메쏘드와문자열슬라이싱을사용하여콜론(:)문자뒤문자열을뽑아내고 float함수를사용하여뽑아낸문자열을부동소수점숫자로변환하세요. Exercise string-methods에서 문자열 메쏘드 문서를 읽어보세요. 어떻게 동작하는가를 이해도를확인하기 위해서몇개를골라실험을해보세요. strip과 replace가 특히 유용합니다. 문서는 좀 혼동스러울 수 있는 구문을 사용합니다. 예를 들어, find(sub[, start[, end]])의 꺾쇠기호는 선택(옵션) 인수를 나타냅니 다.그래서, sub은필수지만, start은선택사항이고,만약 start가 인자로 포함된다면,end는선택이된다.
96 78 제 6 장. 문자열
97 제 7 장 파일 제 1절 영속성(Persistence) 지금까지,프로그램을어떻게 작성하고조건문,함수,반복을사용하여중앙처 리장치(CPU, Central Processing Unit)에 프로그래머의 의도를 커뮤니케이션 하는지 학습했다. 주기억장치(Main Memory)에 어떻게 자료구조를 생성하고 사용하는지도 배웠다. CPU와 주기억장치는 소프트웨어가 동작하고 실행되는 곳이고,모든 생각(thinking) 이발생하는 장소다. 하지만,앞서하드웨어아키텍처를논의했던기억을되살린다면,전원이꺼지게 되면, CPU와주기억장치에저장된모든 것이지워진다.지금까지 작성한프로 그램은파이썬을배우기 위한 일시적으로 재미로연습한 것에불과하다. 소프트웨어 입출력 장치 중앙처리 장치 네트워크 주기억장치 보조기억 장치 이번 장에서보조기억장치(Secondary Memory)혹은파일을 가지고 작업을 시작한다.보조기억장치는전원이꺼져도지워지지않는다.혹은, USB플래쉬 드라이브를 사용한 경우에는 프로그램으로부터 작성한 데이터는 시스템에서 제거되어다른시스템으로전송될수있다.
98 80 제 7 장. 파일 우선텍스트편집기로 작성한텍스트파일을 읽고쓰는 것에초점을맞출 것이 다.나중에데이터베이스소프트웨어를통해서 읽고쓰도록설계된바이너리 파일데이터베이스를 가지고어떻게 작업하는지를살펴볼 것이다. 제 2절 파일열기 하드디스크파일을 읽거나쓸려고할때,파일을열여야(open)한다.파일을열 때 각파일데이터가어디에저장되었는지를알고 있는운영체제와 커뮤니케 이션한다.파일을열때,운영체제에파일이존재하는지확인하고 이름으로파 일을찾도록요청한다. 이번예제에서,파이썬을시작한동일한폴더에저장된 mbox.txt 파일을 연다. 에서 파일을 다운로드할수있다. >>> fhand = open('mbox.txt') >>> print fhand <open file 'mbox.txt', mode 'r' at 0x b0> open이 성공하면, 운영체제는 파일 핸들(file handle)을 반환한다. 파일 핸들(file handle)은 파일에 담겨진 실제 데이터는 아니고, 대신에 데이터를 읽을 수 있도 록사용할수있는 핸들(handle) 이다.요청한파일이존재하고,파일을 읽을 수 있는 적절한 권한이 있다면 이제 핸들이 여러분에게 주어졌다. 열기(Open) 읽기(Read) 쓰기(Write) 닫기(Close) 여러분이 작성한 프로그램 핸들(Handle) mbox.txt Fr om st ephen. m.. Ret ur n- Pat h: <p.. Dat e: Sat, 5 J an.. To: sour ce@col l.. Fr om: st ephen... Subj ect : [ sakai ]... Det ai l s: ht t p: / 파일이존재하지않는다면, open은역추적(traceback)파일열기오류로실패 하고, 파일 콘텐츠에 접근할 핸들도 얻지 못한다. >>> fhand = open('stuff.txt') Traceback (most recent call last): File "<stdin>", line 1, in <module> IOError: [Errno 2] No such file or directory: 'stuff.txt' 나중에try와except를 가지고,존재하지않는파일을열려고하는상황을좀더 우아하게처리할 것이다. 제 3절 텍스트파일과라인 파이썬문자열이문자순서(sequence)로 간주되듯이마찬가지로텍스트파일 은라인순서(sequence)로생각될수있다.예를들어,다음은오픈소스프로젝
99 4. 파일 읽어오기 81 트 개발팀에서다양한참여자들의전자우편활동을기록한텍스트파일샘플 이다. From Sat Jan 5 09:14: Return-Path: <postmaster@collab.sakaiproject.org> Date: Sat, 5 Jan :12: To: source@collab.sakaiproject.org From: stephen.marquard@uct.ac.za Subject: [sakai] svn commit: r content/branches/ Details: 상호 의사소통한 전자우편 전체 파일은 txt 에서 접근 가능하고, 간략한 버젼 파일은 mbox-short.txt에서얻을수있다. 이들파일은다수전자우편메시지를 담고 있는파일로표준포맷으로되어 있다. "From "으로시작하는라인은메 시지본문과구별되고, "From: "으로시작하는라인은본문메시지의 일부다. 더 자세한 정보는 en.wikipedia.org/wiki/mbox에서 찾을 수 있다. 파일을라인으로쪼개기 위해서,새줄(newline)문자로불리는 "줄의끝(end of the line)"을표시하는특수문자가 있다. 파이썬에서, 문자열 상수 역슬래쉬-n(\n)으로 새줄(newline) 문자를 표현한다. 두문자처럼보이지만,사실은단일문자다. 인터프리터에 stuff 에 입력한후 변수를살펴보면,문자열에 \n가 있다.하지만, print문을사용하여문자열을 출력하면,문자열이새줄문자에 의해서두줄로쪼개지는 것을볼수있다. >>> stuff = 'Hello\nWorld!' >>> stuff 'Hello\nWorld!' >>> print stuff Hello World! >>> stuff = 'X\nY' >>> print stuff X Y >>> len(stuff) 3 문자열 'X\nY'의길이는 3 이다.왜냐하면새줄(newline)문자도한문자이기 때문이다. 그래서,파일라인을볼때,라인끝을표시하는새줄(newline)로불리는눈에 보이지않는특수문자가 각줄의끝에 있다고상상할필요가 있다. 그래서, 새줄(newline) 문자는 파일에 있는 문자를 라인으로 분리한다. 제 4절 파일 읽어오기 파일핸들(file handle)이파일 자료를담고 있지않지만, for루프를사용하여 파일 각라인을 읽고라인수를세는 것을쉽게구축할수있다.
100 82 제 7 장. 파일 fhand = open('mbox.txt') count = 0 for line in fhand: count = count + 1 print 'Line Count:', count python open.py Line Count: 파일핸들을 for루프순서(sequence)로사용할수있다. for루프는단순히 파일라인수를세고전체라인수를출력한다. for루프를대략 일반어로풀어 말하면, "파일핸들로표현되는파일 각라인마다,count변수에 1씩더한다" open함수가전체파일을바로 읽지못하는 이유는파일이수기가바이트파 일 크기를 가질 수도 있기 때문이다. open 문장은 파일 크기에 관계없이 파일을 여는데 시간이 동일하게 걸린다. 실질적으로 for 루프가 파일로부터 자료를 읽 어오는역할을한다. for루프를사용해서 이 같은방식으로파일을 읽어올때,새줄(newline)문자 를사용해서파일 자료를라인단위로쪼갠다.파이썬에서새줄(newline)문자 까지 각라인단위로 읽고, for루프가매번반복할때마다 line변수에새줄 (newline)을 마지막 문자로 포함한다. for루프가데이터를한번에한줄씩 읽어오기때문에,데이터를저장할주기억 장치저장공간을소진하지않고,매우큰파일을효과적으로 읽어서라인을셀 수 있다. 각라인별로 읽고,세고,그리고나서폐기되기때문에,매우적은저장 공간을사용해서어떤크기의파일도상기프로그램을사용하여라인을셀수 있다. 만약 주기억장치 크기에 비해서 상대적으로 작은 크기의 파일이라는 것을 안다 면,전체파일을파일핸들로 read메쏘드를사용해서하나의문자열로 읽어올 수 있다. >>> fhand = open('mbox-short.txt') >>> inp = fhand.read() >>> print len(inp) >>> print inp[:20] From stephen.marquar 상기 예제에서, mbox-short.txt 전체 파일 콘텐츠(94,626 문자)를 변수 inp로 바로 읽었다.문자열슬라이싱을사용해서 inp에저장된문자열 자료첫20문 자를 출력한다. 파일이 이런방식으로 읽혀질때,모든라인과새줄(newline)문자를포함한모든 문자는변수inp에대입된매우큰문자열이다.파일데이터가 컴퓨터주기억장 치가안정적으로 감당해낼수있을때만, 이런형식의 open함수가사용될수 있다는 것을기억하라. 만약주기억장치가 감당해낼수없는매우파일크기가크다면, for나 while 루프를 사용해서 파일을 쪼개서 읽는 프로그램을 작성해야 한다.
101 5. 파일 검색 83 제 5절 파일 검색 파일데이터를 검색할때,흔한패턴은파일을 읽고,대부분라인은 건너뛰고,특 정기준을만족하는라인만처리하는 것이다. 간단한 검색메카니즘을구현하기 위해서 파일을 읽는 패턴과 문자열 메쏘드를 조합한다. 예를들어,파일을 읽고, From: 으로시작하는라인만출력하고자한다면, startswith문자열메쏘드를사용해서원하는접두사로시작하는라인만을선 택한다. fhand = open('mbox-short.txt') for line in fhand: if line.startswith('from:') : print line 이프로그램이실행하면다음출력값을얻는다. From: stephen.marquard@uct.ac.za From: louis@media.berkeley.edu From: zqian@umich.edu From: rjlowe@iupui.edu... From: 으로만 시작하는 라인만 출력하기 때문에 출력값은 훌륭해 보인다. 하 지만,왜여분으로빈라인이보이는 걸까?원인은눈에보이지않는새줄(newline)문자때문이다. 각라인이새줄(newline)로끝나서변수 line에새줄(newline)이 포함되고 print문이 추가로 새줄(newline)을 추가해서 결국 우리가 보 기에는두줄효과가나타난다. 마지막문자를제외하고모든 것을출력하기 위해서라인슬라이싱(slicing)을 할수 있지만,좀더 간단한접근법은다음과 같이문자열오른쪽끝에서부터 공 백을 벗겨내는 rstrip 메쏘드를 사용하는 것인다. fhand = open('mbox-short.txt') for line in fhand: line = line.rstrip() if line.startswith('from:') : print line 프로그램을실행하면,다음출력값을얻는다. From: stephen.marquard@uct.ac.za From: louis@media.berkeley.edu From: zqian@umich.edu From: rjlowe@iupui.edu From: zqian@umich.edu From: rjlowe@iupui.edu From: cwen@iupui.edu...
102 84 제 7 장. 파일 파일처리프로그램이점점더복잡해짐에따라 continue를사용해서 검색루 프(search loop)를구조화할필요가 있다. 검색루프의기본아이디어는 흥미 로운 라인을집중적으로찾고, 흥미롭지않은 라인은효과적으로 건너뛰는 것이다.그리고나서흥미로운라인을찾게되면,그라인에서특정연산을수행 하는 것이다. 다음과 같이루프를구성해서흥미롭지않은라인은 건떠뛰는패턴을따르게 한다. fhand = open('mbox-short.txt') for line in fhand: line = line.rstrip() # Skip 'uninteresting lines' if not line.startswith('from:') : continue # Process our 'interesting' line print line 프로그램의출력값은동일하다.흥미롭지않는라인은 From: 으로시작하 지 않는 라인이라 continue문을 사용해서 건너뛴다. 흥미로운 라인 (즉, From: 으로 시작하는 라인)에 대해서는 연산처리를 수행한다. find문자열메쏘드를사용해서 검색문자열이라인어디에 있는지를찾아주는 텍스트 편집기 검색기능을 모사(simulation)할 수 있다. find 메쏘드는 다른 문 자열내부에 검색하는문자열이 있는지찾고,문자열 위치를반환하거나,만약 문자열이없다면 (남아프리카케이프타운 대학으로부터왔다)문자열을포함하는라인을 검색하기 위해다음과 같이루 프를 작성한다. fhand = open('mbox-short.txt') for line in fhand: line = line.rstrip() if line.find('@uct.ac.za') == -1 : continue print line 출력결과는다음과 같다. From stephen.marquard@uct.ac.za Sat Jan 5 09:14: X-Authentication-Warning: set sender to stephen.marquard@uct.ac.za using -f From: stephen.marquard@uct.ac.za Author: stephen.marquard@uct.ac.za From david.horwitz@uct.ac.za Fri Jan 4 07:02: X-Authentication-Warning: set sender to david.horwitz@uct.ac.za using -f From: david.horwitz@uct.ac.za Author: david.horwitz@uct.ac.za... 제 6절 사용자가파일명을선택하게만들기 매번다른파일을처리할때마다파이썬코드를편집하고싶지는않다.매번프 로그램이실행될때마다,파일명을사용자가 입력하도록만드는 것이좀더 유
103 7. try, except, open사용하기 85 용할 것이다.그래서파이썬코드를바꾸지않고,다른파일에대해서도동일한 프로그램을사용하도록만들자. 다음과 같이 raw_input을 사용해서 사용자로부터 파일명을 읽어 프로그램을 실행하는 것이단순하다. fname = raw_input('enter the file name: ') fhand = open(fname) count = 0 for line in fhand: if line.startswith('subject:') : count = count + 1 print 'There were', count, 'subject lines in', fname 사용자로부터파일명을 읽고변수fname에저장하고,그파일을연다. 이제다른 파일에대해서도반복적으로프로그램을실행할수있다. python search6.py Enter the file name: mbox.txt There were 1797 subject lines in mbox.txt python search6.py Enter the file name: mbox-short.txt There were 27 subject lines in mbox-short.txt 다음절을엿보기전에,상기프로그램을살펴보고 자신에게다음을질문해보 자. "여기서어디가 잘못될수있는가?"혹은 "이 작고멋진프로그램에트레 이스백(traceback)을남기고바로끝나게하여, 결국사용자눈에는좋지않은 프로그램이라는 인상을남길수있도록우리의 친절한사용자는무엇을할수 있을까? 제 7절 try, except, open사용하기 제가여러분에게엿보지말라고말씀드렸습니다. 이번이마지막기회입니다. 사용자가파일명이아닌뭔가다른 것을 입력하면어떻게될까요? python search6.py Enter the file name: missing.txt Traceback (most recent call last): File "search6.py", line 2, in <module> fhand = open(fname) IOError: [Errno 2] No such file or directory: 'missing.txt' python search6.py Enter the file name: na na boo boo Traceback (most recent call last): File "search6.py", line 2, in <module> fhand = open(fname) IOError: [Errno 2] No such file or directory: 'na na boo boo' 웃지마시구요, 사용자는 결국 여러분이 작성한 프로그램을 망가뜨리기 위해 고 의든악의를 가지든 가능한모든수단을 강구할 것입니다.사실,소프트웨어 개
104 86 제 7 장. 파일 발팀의 중요한 부분은 품질 보증(Quality Assurance, QA)이라는 조직이다. 품 질보증조직은프로그래머가만든소프트웨어를망가뜨리기 위해 가능한말도 안되는 것을합니다. 사용자가 소프트웨어를 제품으로 구매하거나, 주문형으로 개발하는 프로그램 에대해월급을지급하던지관계없이품질보증조직은프로그램이사용자에게 전달되기전까지프로그램오류를발견할책임이 있다.그래서품질보증조직은 프로그래머의최고의 친구다. 프로그램오류를찾았기때문에,try/except구조를사용해서오류를우아하게 고쳐봅시다.open호출이 잘못될수있다고 가정하고,open호출이실패할때를 대비해서 다음과 같이 복구 코드를 추가한다. fname = raw_input('enter the file name: ') try: fhand = open(fname) except: print 'File cannot be opened:', fname exit() count = 0 for line in fhand: if line.startswith('subject:') : count = count + 1 print 'There were', count, 'subject lines in', fname exit함수가프로그램을끝낸다. 결코돌아오지않는함수를호출한 것이다. 이 제사용자혹은품질보증조직에서올바르지않거나어처구니없는파일명을 입력했을때, catch 로 잡아서우아하게복구한다. python search7.py Enter the file name: mbox.txt There were 1797 subject lines in mbox.txt python search7.py Enter the file name: na na boo boo File cannot be opened: na na boo boo 파이썬프로그램을 작성할때open호출을보호하는 것은 try, except의적절 한사용예제가된다. 파이썬방식(Python way) 으로무언가를 작성할때, 파이썬스러운(Pythonic) 이라는 용어를 사용한다. 상기 파일을 여는 예제는 파 이썬스러운방식의좋은예가된다고말한다. 파이썬에좀더 자신감이생기게되면,다른파이썬프로그래머와동일한문제에 대해두가지동치하는해답을 가지고어떤접근법이좀더 "파이썬스러운지"에 대한현답을찾는데도관여하게된다. "좀더파이썬스럽게"되는 이유는프로그래밍이엔지니어링적인면과예술적 인면을동시에 가지고 있기때문이다.항상무언가를단지 작동하는 것에만 관심이 있지않고,프로그램으로 작성한해결책이좀더우아하고,다른동료에 의해서우아한 것으로 인정되기를또한원합니다.
105 8. 파일에 쓰기 87 제 8절 파일에쓰기 파일에쓰기 위해서는두번째매개변수로'w'모드로파일을열어야한다. >>> fout = open('output.txt', 'w') >>> print fout <open file 'output.txt', mode 'w' at 0xb7eb2410> 파일이 이미존재하는데쓰기모드에서파일을여는 것은 이전데이터를모두지 워버리고,깨끗한파일상태에서다시시작되니주의가필요하다.만약파일이 존재하지않는다면,새로운파일이생성된다. 파일 핸들 객체의 write 메쏘드는 데이터를 파일에 저장한다. >>> line1 = 'This here's the wattle,\n' >>> fout.write(line1) 다시한번,파일 객체는마지막포인터가어디에 있는지 위치를추적해서,만약 write 메쏘드를 다시 호출하게 되면, 새로운 데이터를 파일 끝에 추가한다. 라인을끝내고싶을때,명시적으로새줄(newline)문자를삽입해서파일에쓰 도록라인끝을필히관리해야한다. print문은 자동적으로새줄(newline)을추가하지만,write메쏘드는 자동적으 로 새줄(newline)을 추가하지는 않는다. >>> line2 = 'the emblem of our land.\n' >>> fout.write(line2) 파일쓰기가끝났을때,파일을필히닫아야한다.파일을닫는 것은데이터마 지막 비트까지 디스크에 물리적으로 쓰여져서, 전원이 나가더라도 자료가 유실 되지않는역할을한다. >>> fout.close() 파일 읽기로연파일을닫을수있지만,몇개파일을열어놓았다면약간단정 치못하게끝날수있습니다.왜냐하면프로그램이종료될때열린모든파일이 닫혀졌는지파이썬이확인하기때문이다.파일에쓰기를할때는,파일을명시 적으로닫아서예기치못한 일이발생할여지를없애야한다. 제 9절 디버깅 파일을 읽고쓸때, 공백때문에종종문제에봉착한다. 이런종류의오류는 공백, 탭, 새줄(newline)이 눈에 보이지 않기 때문에 디버그하기도 쉽지 않다. >>> s = '1 2\t 3\n 4' >>> print s 내장함수repr이도움이될수있다. 인자로 임의 객체를 잡아 객체문자열표현 으로 반환한다. 문자열 공백문자는 역슬래쉬 순서(sequence)로 나타냅니다.
106 88 제 7 장. 파일 >>> print repr(s) '1 2\t 3\n 4' 디버깅에도움이될수있다. 여러분이봉착하는또다른문제는다른시스템에서는라인끝을표기하기 위 해서다른문자를사용한다는점이다.어떤시스템은 \n 으로새줄(newline)을 표기하고, 다른 시스템은 \r으로 반환 문자(return character)를 사용한다. 둘 다모두사용하는시스템도 있다.파일을다른시스템으로 이식한다면, 이러한 불일치가문제를야기한다. 대부분의시스템에는 A포맷에서 B포멧으로변환하는 응용프로그램이 있다. wikipedia.org/wiki/newline에서 응용프로그램을찾을수있고,좀더 많은 것을 읽을수있다.물론,여러분이직접프로그램을 작성할수도 있다. 제 10절 용어정의 잡기(catch): try와 except문을사용해서프로그램이끝나는예외상황을방 지하는 것. 새줄(newline): 라인의 끝을 표기 위한 파일이나 문자열에 사용되는 특수 문자. 파이썬스러운(Pythonic): 파이썬에서 우아하게 작동하는 기술. try와 catch를 사용하는 것은 파일이 없는 경우를 복구하는 파이썬스러운 방식이다. 품질보증(Quality Assurance, QA): 소프트웨어제품의전반적인품질을보중 하는데집중하는사람이나조직.품질보증은소프트웨어제품을시험하 고, 제품이 시장에 출시되기 전에 문제를 확인하는데 관여한다. 텍스트파일(text file): 하드디스크 같은영구저장소에저장된 일련의문자집 합. 제 11절 연습문제 Exercise 7.1 파일을 읽고한줄씩파일의내용을모두대문자로출력하는프로 그램을 작성하세요.프로그램을싱행하면다음과같이보일것입니다. python shout.py Enter a file name: mbox-short.txt FROM STEPHEN.MARQUARD@UCT.AC.ZA SAT JAN 5 09:14: RETURN-PATH: <POSTMASTER@COLLAB.SAKAIPROJECT.ORG> RECEIVED: FROM MURDER (MAIL.UMICH.EDU [ ]) BY FRANKENSTEIN.MAIL.UMICH.EDU (CYRUS V2.3.8) WITH LMTPA; SAT, 05 JAN :14: 파일을 다운로드 받으세요.
107 11. 연습문제 89 Exercise 7.2 파일명을 입력받아,파일을 읽고,다음형식의라인을찾는프로그 램을 작성하세요. X-DSPAM-Confidence: X-DSPAM-Confidence: 로 시작하는 라인을 만나게 되면, 부동 소수점 숫자를 뽑아내기 위해해당라인을별도로보관하세요.라인수를세고,라인으로부터 스팸 신뢰값의 총계를 계산하세요. 파일의 끝에 도달할 했을 때, 평균 스팸 신뢰 도를 출력하세요. Enter the file name: mbox.txt Average spam confidence: Enter the file name: mbox-short.txt Average spam confidence: mbox.txt와 mbox-short.txt 파일에 작성한 프로그램을 시험하세요. Exercise 7.3 때때로,프로그래머가지루해지거나,약간 재미를목적으로,프 로그램에 무해한 부활절 달걀(Easter Egg, en.wikipedia.org/wiki/easter_ egg_(media))을넣습니다.사용자가파일명을 입력하는프로그램을변형시켜, na na boo boo 로파일명을정확하게 입력했을때, 재미있는메시지를출력하는 프로그램을 작성하세요.파일이존재하거나,존재하지않는다른모든파일에 대해서도정상적으로 작동해야합니다.여기프로그램을실행한견본이 있습 니다. python egg.py Enter the file name: mbox.txt There were 1797 subject lines in mbox.txt python egg.py Enter the file name: missing.tyxt File cannot be opened: missing.tyxt python egg.py Enter the file name: na na boo boo NA NA BOO BOO TO YOU - You have been punk'd! 프로그램에 부활절 달걀을 넣도록 격려하지는 않습니다. 단지 연습입니다.
108 90 제 7 장. 파일
109 제 8 장 리스트 (List) 제 1 절 리스트는 순서(sequence)다. 문자열처럼, 리스트(list)는 값의 순서(sequence)다. 문자열에서, 값은 문자지만, 리스트에서는 임의 자료형(type)도 될 수 있다. 리스트 값은 요소(elements)나 때때로 항목(items)으로 불린다. 신규리스틀생성하는방법은여러 가지가 있다. 가장 간단한방법은꺾쇠괄호 ([와])로요소를 감싸는 것이다. [10, 20, 30, 40] ['crunchy frog', 'ram bladder', 'lark vomit'] 첫번째 예제는 4개 정수 리스트다. 두번째 예제는 3개 문자열 리스트다. 문자열 요소가동일한 자료형(type)일필요는없다.다음리스트는문자열,부동소수점 숫자,정수, (아!)또다른리스트를담고 있다. ['spam', 2.0, 5, [10, 20]] 또 다른 리스트 내부에 리스트가 중첩(nested)되어 있다. 어떤요소도담고 있지않는리스트를빈리스트(empty list)라고부르고,빈꺾 쇠괄호( [] )로생성한다. 예상했듯이, 리스트 값을 변수에 대입할 수 있다. >>> cheeses = ['Cheddar', 'Edam', 'Gouda'] >>> numbers = [17, 123] >>> empty = [] >>> print cheeses, numbers, empty ['Cheddar', 'Edam', 'Gouda'] [17, 123] [] 제 2절 리스트는변경가능하다. 리스트요소에접근하는구문은문자열문자에접근하는 것과동일한꺾쇠괄호 연산자다.꺽쇠괄호내부표현식은 인덱스를명세한다.기억할 것은 인덱스는
110 92 제 8 장. 리스트 (List) 0 에서부터 시작한다는 것이다. >>> print cheeses[0] Cheddar 문자열과달리,리스트항목순서를바꾸거나,리스트에새로운항목을다시대 입할수있기때문에리스트는변경가능하다.꺾쇠괄호연산자가대입문왼쪽 편에나타날때,새로대입될리스트요소를나타낸다. >>> numbers = [17, 123] >>> numbers[1] = 5 >>> print numbers [17, 5] 리스트numbers첫번째요소는 123 값을 가지고 있었으나, 이제 5 값을 가진다. 리스트를 인덱스와요소의관계로생각할수있다. 이관계를매핑(mapping) 이라고부른다. 각각의 인덱스는요소중하나에대응( maps to )된다. 리스트 인덱스는문자열 인덱스와동일한방식으로동작한다. 어떠한정수표현식도 인덱스로사용할수있다. 존재하지않는요소를 읽거나쓰려고하면,인덱스 오류 (IndexError) 가발생한다. 인덱스가 음의 값이면, 리스트 끝에서부터 역으로 센다. in연산자도또한리스트에서동작하니사용할수있다. >>> cheeses = ['Cheddar', 'Edam', 'Gouda'] >>> 'Edam' in cheeses True >>> 'Brie' in cheeses False 제 3절 리스트운행법 리스트 요소를 운행하는 가장 흔한 방법은 for문을 사용하는 것이다. 문자열에 서사용한 것과구문은동일하다. for cheese in cheeses: print cheese 리스트요소를 읽기만한다면 이것만으로도 잘동작한다.하지만,리스트요소 를쓰거나, 갱신하는 경우, 인텍스가필요하다.리스트요소를쓰거나 갱신하는 일반적인 방법은 range와 len 함수를 조합하는 것이다. for i in range(len(numbers)): numbers[i] = numbers[i] * 2
111 4. 리스트 연산자 93 상기루프는리스트를운행하고 각요소를 갱신한다. len함수는리스트요소 갯수를반환한다. range함수는 0에서 n 1까지리스트 인텍스를반환한다. 여기서, n은리스트길이다.매번루프가반복될때마다, i는다음요소 인덱스 를얻는다.몸통부문대입문은 i를사용해서요소의 이전 값을 읽고새값을 대입한다. 빈리스트에대해서for문은 결코몸통부문을실행하지않는다. for x in empty: print 'This never happens.' 리스트가또다른리스트를담을수있지만,중첩된리스트는여전히요소하나 로 간주된다.다음리스트길이는 4 이다. ['spam', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]] 제 4절 리스트연산자 +연산자는리스트를 결합한다. >>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> c = a + b >>> print c [1, 2, 3, 4, 5, 6] 유사하게*연산자는주어진횟수만큼리스트를반복한다. >>> [0] * 4 [0, 0, 0, 0] >>> [1, 2, 3] * 3 [1, 2, 3, 1, 2, 3, 1, 2, 3] 첫예제는 [0]을 4회반복한다.두번째예제는 [1, 2, 3]리스트를 3회반복 한다. 제 5 절 리스트 슬라이스(List slices) 슬라이스연산자는리스트에도또한동작한다. >>> t = ['a', 'b', 'c', 'd', 'e', 'f'] >>> t[1:3] ['b', 'c'] >>> t[:4] ['a', 'b', 'c', 'd'] >>> t[3:] ['d', 'e', 'f'] 첫번째 인덱스를생략하면,슬라이스는처음부터시작한다.두번째 인덱스를 생략하면,슬라이스는끝까지 간다.그래서양쪽의 인덱스를생략하면,슬라이 스 결과는전체리스트를복사한 것이된다.
112 94 제 8 장. 리스트 (List) >>> t[:] ['a', 'b', 'c', 'd', 'e', 'f'] 리스트는변경이 가능하기때문에리스트를접고,돌리고,훼손하는연산을수 행하기 전에 복사본을 만들어 두는 것이 유용하다. 대입문왼편의슬라이스연산자로복수의요소를 갱신할수있다. >>> t = ['a', 'b', 'c', 'd', 'e', 'f'] >>> t[1:3] = ['x', 'y'] >>> print t ['a', 'x', 'y', 'd', 'e', 'f'] 제 6절 리스트메쏘드 파이썬은 리스트에 연산하는 메쏘드를 제공한다. 예를 들어, 덧붙이기 (append)메쏘드는리스트끝에신규요소를추가한다. >>> t = ['a', 'b', 'c'] >>> t.append('d') >>> print t ['a', 'b', 'c', 'd'] 확장 (extend)메쏘드는 인자로리스트를받아모든요소를리스트에덧붙 인다. >>> t1 = ['a', 'b', 'c'] >>> t2 = ['d', 'e'] >>> t1.extend(t2) >>> print t1 ['a', 'b', 'c', 'd', 'e'] 상기예제는t2리스트를변경없이그냥둔다. 정렬 (sort)메쏘드는낮음에서높음으로리스트요소를정렬한다. >>> t = ['d', 'c', 'e', 'b', 'a'] >>> t.sort() >>> print t ['a', 'b', 'c', 'd', 'e'] 대부분의 리스트 메쏘드는 보이드(void)여서, 리스트를 변경하고 None을 반환 한다.우연히t = t.sort() 이렇게 작성한다면, 결과에실망할 것이다. 제 7절 요소삭제 리스트요소를삭제하는방법이몇가지 있다.리스트요소 인덱스를알고 있다 면, 팝 (pop) 메쏘드를 사용한다.
113 8. 리스트와 함수 95 >>> t = ['a', 'b', 'c'] >>> x = t.pop(1) >>> print t ['a', 'c'] >>> print x b 팝(pop)메쏘드는리스트를변경하여제거된요소를반환한다. 인덱스를주지 않으면,마지막요소를지우고반환한다. 요소에서 제거된 값이 필요없다면, del 연산자를 사용한다. >>> t = ['a', 'b', 'c'] >>> del t[1] >>> print t ['a', 'c'] (인덱스가아닌)제거할요소값을알고 있다면,제거 (remove)메쏘드를사용 한다. >>> t = ['a', 'b', 'c'] >>> t.remove('b') >>> print t ['a', 'c'] 제거 (remove)메쏘드의반환값은none이다. 하나 이상의 요소를 제거하기 위해서, 슬라이스 인덱스(slice index)와 del을 사 용한다. >>> t = ['a', 'b', 'c', 'd', 'e', 'f'] >>> del t[1:5] >>> print t ['a', 'f'] 마찬가지로,슬라이스는두번째 인덱스를포함하지않는두번째 인덱스까지 모든요소를선택한다. 제 8절 리스트와함수 루프를 작성하지않고도리스트를빠르게살펴볼수있는리스트에적용할수 있는내장함수가많이 있다. >>> nums = [3, 41, 12, 9, 74, 15] >>> print len(nums) 6 >>> print max(nums) 74 >>> print min(nums) 3 >>> print sum(nums) 154 >>> print sum(nums)/len(nums) 25
114 96 제 8 장. 리스트 (List) 리스트요소가숫자일때만, sum()함수는동작한다. max(), len(),등등다른 함수는문자열리스트나,비교 가능한다른 자료형(type)리스트에사용될수 있다. 리스트를사용해서,앞서 작성한프로그램을다시 작성해서사용자가 입력한 숫자목록평균을 계산한다. 우선 리스트 없이 평균을 계산하는 프로그램: total = 0 count = 0 while ( True ) : inp = raw_input('enter a number: ') if inp == 'done' : break value = float(inp) total = total + value count = count + 1 average = total / count print 'Average:', average 상기프로그램에서, count와sum변수를사용해서반복적으로사용자가숫자 를 입력하면 값을 저장하고, 지금까지 사용자가 입력한 누적 합계를 계산한다. 단순하게,사용자가 입력한 각숫자를기억하고내장함수를사용해서프로그램 마지막에합계와 갯수를 계산한다. numlist = list() while ( True ) : inp = raw_input('enter a number: ') if inp == 'done' : break value = float(inp) numlist.append(value) average = sum(numlist) / len(numlist) print 'Average:', average 루프가시작되기전빈리스트를생성하고,매번숫자를 입력할때마다숫자를 리스트에추가한다.프로그램마지막에 간단하게리스트총합을 계산하고,평 균을 산출하기 위해서 입력한 숫자 개수로 나눈다. 제 9절 리스트와문자열 문자열은 문자 순서(sequence)이고, 리스트는 값 순서(sequence)이다. 하지만 리스트문자는문자열과 같지는않다.문자열에서리스트문자로변환하기 위 해서,list를사용한다. >>> s = 'spam' >>> t = list(s) >>> print t ['s', 'p', 'a', 'm']
115 10. 라인파싱하기(Parsing) 97 list는내장함수 이름이기때문에,변수명으로사용하는 것을피해야한다.l을 사용하면1처럼보이기때문에피한다.그래서,t를사용했다. list함수는문자열을 각각의문자로쪼갠다.문자열단어로쪼개려면,분할 (split)메쏘드를사용할수있다. >>> s = 'pining for the fjords' >>> t = s.split() >>> print t ['pining', 'for', 'the', 'fjords'] >>> print t[2] the 분할 (split)메쏘드를사용해서문자열을리스트토큰으로쪼개면, 인덱스 연산자( [] )를사용하여리스트의특정단어를볼수있다. 옵션 인자로단어 경계로어떤문자를사용할 것인지지정하는데사용되는구 분자 (delimiter)를활용하여분할 (split)메쏘드를호출한다.다음예제는구 분자로하이픈( - )을사용한사례다. >>> s = 'spam-spam-spam' >>> delimiter = '-' >>> s.split(delimiter) ['spam', 'spam', 'spam'] 합병 (join)메쏘드는분할 (split)메쏘드의역이다.문자열리스트를받아 리스트요소를연결한다.합병 (join)은문자열메쏘드여서,구분자를호출하 여매개변수로넘길수있다. >>> t = ['pining', 'for', 'the', 'fjords'] >>> delimiter = ' ' >>> delimiter.join(t) 'pining for the fjords' 상기의 경우,구분자가 공백문자여서결합 (join)메쏘드가단어사이에 공 백을넣는다. 공백없이문자열을 결합하기 위해서,구분자로빈문자열 ''을 사용한다. 제 10절 라인파싱하기(Parsing) 파일을 읽을때통상,단지전체라인을출력하는 것말고뭔가다른 것을하고자 한다.종종 흥미로운라인을 찾아서라인을파싱(parse)하여흥미로운 부분 을찾고자한다. From 으로시작하는라인에서요일을찾고자하면어떨까? From stephen.marquard@uct.ac.za Sat Jan 5 09:14: 이런종류의문제에직면했을때,분할 (split)메쏘드가매우효과적이다. 작 은프로그램을 작성하여 From 으로시작하는라인을찾고분할 (split)메 쏘드로파싱하고라인의흥미로운부분을출력한다.
116 98 제 8 장. 리스트 (List) fhand = open('mbox-short.txt') for line in fhand: line = line.rstrip() if not line.startswith('from ') : continue words = line.split() print words[2] if문의축약형태를사용하여 continue 문을 if문과동일한라인에놓았다. if 문 축약 형태는 continue 문을 들여쓰기를 다음 라인에 한 것과 동일하다. 프로그램은다음을출력한다. Sat Fri Fri Fri... 나중에,매우정교한기술에대해서학습해서정확하게 검색하는비트(bit)수준 정보를찾아내기 위해서 작업할라인을선택하고,어떻게해당라인을뽑아낼 것이다. 제 11절 객체와 값(value) 다음대입문을실행하면, a = 'banana' b = 'banana' a와b모두문자열을참조하지만,두변수가동일한문자열을참조하는지알수 없다.두가지 가능한상태가 있다. a b banana banana a b banana 한 가지 경우는 a와b가 같은 값을 가지는다른두객체를참조하는 것이다.두 번째 경우는 같은 객체를참조하는 것이다. 두변수가동일한 객체를참조하는지를확인하기 위해서, is연산자가사용 된다. >>> a = 'banana' >>> b = 'banana' >>> a is b True 이 경우,파이썬은하나의문자열 객체를생성하고 a와b모두동일한 객체를 참조한다. 하지만,리스트두개를생성할때, 객체가두개다.
117 12. 에일리어싱(Aliasing) 99 >>> a = [1, 2, 3] >>> b = [1, 2, 3] >>> a is b False 상기의 경우, 두 개의 리스트는 동등하다고 말할 수 있다. 왜냐하면 동일한 요소 를 가지고 있기 때문이다. 하지만, 같은 객체는 아니기 때문에 동일하지는 않다. 두 개의 객체가동일하다면,두객체는또한등등하다.하지만,동등하다고해서 반듯이동일하지는않다. 지금까지 객체(object) 와 값(value) 을 구분 없이 사용했지만, 객체가 값을 가진다라고말하는 것이좀더정확하다. a = [1,2,3] 을실행하면, a는특별 한순서요소값을 갖는리스트 객체로참조한다.만약또다른리스트가동일한 요소를 가진다면,그리스트는 같은 값을 가진다고말한다. 제 12 절 에일리어싱(Aliasing) a가 객체를 참조하고, b = a 대입하다면, 두 변수는 동일한 객체를 참조한다. >>> a = [1, 2, 3] >>> b = a >>> b is a True 객체와변수의연관짖는 것을참조(reference)라고한다.상기의 경우동일한 객체에두개의참조가 있다. 하나 이상의참조를 가진 객체는한개 이상의 이름을 갖게되어서, 객체가에일 리어스(aliased)되었다고한다. 만약에일리어스된 객체가변경 가능하면,변화의여파는다른 객체에도파급 된다. >>> b[0] = 17 >>> print a [17, 2, 3] 이와 같은행동이 유용하기도하지만,오류를발생시키기도쉽다. 일반적으로, 변경가능한 객체(mutable object)로 작업할 때 에일리어싱을 피하는 것이 안전 하다. 문자열 같이변경불가능한 객체에에일리어싱은그렇게문제가되지않는다. a = 'banana' b = 'banana' 상기예제에서, a와b가동일한문자열을참조하든참조하지않든 거의차이가 없다.
118 100 제 8 장. 리스트 (List) 제 13절 리스트 인수 리스트를함수에 인자로전달할때,함수는리스트에참조를얻는다.만약함수 가리스트매개변수를변경한다면,호출자는변경된 것을보게된다.예를들어, delete_head는 리스트에서 첫 요소를 제거한다. def delete_head(t): del t[0] 다음에 delete_head 함수가 사용된 예제가 있다. >>> letters = ['a', 'b', 'c'] >>> delete_head(letters) >>> print letters ['b', 'c'] 매개 변수 t와 변수 letters는 동일한 객체에 대한 에일리어스(aliases)다. 리스트를변경하는연산자와신규리스트를생성하는연산자를구별하는 것이 중요하다. 예를 들어, 덧붙이기 (append) 메쏘드는 리스트를 변경하지만, + 연 산자는신규리스트를생성한다. >>> t1 = [1, 2] >>> t2 = t1.append(3) >>> print t1 [1, 2, 3] >>> print t2 None >>> t3 = t1 + [3] >>> print t3 [1, 2, 3] >>> t2 is t3 False 리스트를변경하는함수를 작성할때, 이차이는매우중요하다.예를들어,다음 함수는 리스트의 머리 부문(head)을 삭제하지 않는다. def bad_delete_head(t): t = t[1:] # 틀림(WRONG)! 슬라이스연산자는새로운리스트를생성하고대입문을통해서 t가참조하게 하지만,어떤 것도 인자로전달된리스트에는영향도주지못한다. 대안은신규리스트를생성하고반환하는함수를 작성하는 것이다.예를들어, tail은 리스트의 첫 요소를 제외하고 모든 요소를 반환한다. def tail(t): return t[1:] 상기함수는원리시트를변경하지는않는다.다음에사용예시가 있다. >>> letters = ['a', 'b', 'c'] >>> rest = tail(letters) >>> print rest ['b', 'c']
119 14. 디버깅 101 Exercise 8.1 리스트를 인자로받아리스트를변경하여,첫번째요소와마지막 요소를 제거하고 None을 반환하는 chop 함수를 작성하게요. 그리고나서,리스트를 인자로받아처음과마지막요소를제외한나머지요소를 새로운 리스트로 반환하는 middle 함수를 작성하세요. 제 14절 디버깅 부주의한리스트사용이나변경가능한 객체를사용하는 경우디버깅을오래할 수 있다.다음에 일반적인함정 유형과회피하는방법을소개한다. 1. 대부분의리스트메쏘드는 인자를변경하고, None을반환한다. 이는새 로운문자열을반환하고원문자열은그대로두는문자열의 경우와정반 대다. 다음과 같이 문자열 코드를 쓰는데 익숙해져 있다면, word = word.strip() 다음과 같이리스트코드를 작성하고싶은 유혹이 있을 것이다. t = t.sort() # 틀림(WRONG)! 정렬 (sort)메쏘드는none을반환하기때문에,리스트t로수행한다음 연산은실패한다. 리스트 메쏘드와 연산자를 사용하기 전에, 문서를 주의깊게 읽고, 인 터랙티브 모드에서 시험하는 것을 권한다. 리스트가 문자열과 같은 다른 순서(sequence)와 공유하는 메쏘드와 연산자는 docs.python. org/lib/typesseq.html 에 문서화되어 있다. 변경가능한 순서(sequence)에만 적용되는 메쏘드와 연산자는 docs.python.org/lib/ typesseq-mutable.html에 문서화되어 있다. 2. 관용구를 선택하고 고수하라. 리스트와관련된문제 일부는리스트를 가지고할수있는 것이너무많다 는 것이다.예를들어,리스트에서요소를제거하기 위해서, pop, remove, del,혹은슬라이스대입(slice assignment)도사용할수있다.요소를추 가하기 위해서덧붙이기 (append)메쏘드나+연산자를사용할수있다. 하지만 다음이 맞다는 것을 잊지 마세요. t.append(x) t = t + [x] 하지만,다음은 잘못됐다. t.append([x]) t = t.append(x) t + [x] t = t + x # 틀림(WRONG)! # 틀림(WRONG)! # 틀림(WRONG)! # 틀림(WRONG)!
120 102 제 8 장. 리스트 (List) 인터랙티브모드에서 각각을연습해보고제대로 이해하고 있는지확인해 보세요.마지막한개만실행오류를하고,다른세가지는모두 작동하지만, 잘못된 것을수행함을주목하세요. 3. 에일리어싱을 회피하기 위해서 사본 만들기. 인자를변경하는정렬 (sort)같은메쏘드를사용하지만,원리스트도보 관되길원한다면,사본을만든다. orig = t[:] t.sort() 상기예제에서원리스트는그대로둔상태로새로정렬된리스트를반환 하는내장함수sorted를사용할수있다.하지만 이 경우에는,변수명으로 sorted를 사용하는 것을 피해야 한다! 4. 리스트,분할 (split),파일 파일을 읽고파싱할때,프로그램이중단될수있는 입력값을마주할수많 은기회가 있다.그래서파일을훑어 건초더미에서바늘 을찾는프로그 램을 작성할때사용한 가디언패턴(guardian pattern)을다시살펴보는 것은좋은생각이다. 파일라인에서요일을찾는프로그램을다시살펴보자. From stephen.marquard@uct.ac.za Sat Jan 5 09:14: 각라인을단어로나누었기때문에,startswith를사용하지않고,라인에 관심있는단어가 있는지살펴보기 위해서단순하게 각라인의첫단어를 살펴본다.다음과 같이 continue문을사용해서 From 이없는라인을 건너뛴다. fhand = open('mbox-short.txt') for line in fhand: words = line.split() if words[0]!= 'From' : continue print words[2] 프로그램이훨씬 간단하고,파일끝에 있는새줄(newline)을제거하기 위 해 rstrip을 사용할 필요도 없다. 하지만, 더 좋아졌는가? python search8.py Sat Traceback (most recent call last): File "search8.py", line 5, in <module> if words[0]!= 'From' : continue IndexError: list index out of range 작동하는 것 같지만,첫줄에 Sat를출력하고나서역추적오류(traceback error)로프로그램이정상동작에실패한다.무엇이 잘못되었을까?어딘 가엉망이된데이터가 있어우아하고,총명하며,매우파이썬스러운프로 그램을망가뜨린건가?
121 14. 디버깅 103 오랜동안프로그램을 응시하고머리를짜내거나,다른사람에게도움을 요청할수있지만,빠르고현명한접근법은 print문을추가하는 것이다. print문을넣는 가장좋은 장소는프로그램이동작하지않는라인앞이 적절하고, 프로그램 실패를 야기할 것 같은 데이터를 출력한다. 이접근법이많은라인을출력하지만,즉석에서문제에대해서손에 잡히 는단서는최소한준다.그래서 words를출력하는출력문을 5번째라인 앞에 추가한다. Debug: 를 접두어로 라인에 추가하여, 정상적인 출력과 디버그출력을구분한다. for line in fhand: words = line.split() print 'Debug:', words if words[0]!= 'From' : continue print words[2] 프로그램을실행할때,많은출력결과가스크롤되어화면 위로지나간다. 마지막에 디버그 결과물과 역추적(traceback)을 보고 역추적(traceback) 바로앞에서무슨 일이생겼는지알수있다. Debug: ['X-DSPAM-Confidence:', '0.8475'] Debug: ['X-DSPAM-Probability:', '0.0000'] Debug: [] Traceback (most recent call last): File "search9.py", line 6, in <module> if words[0]!= 'From' : continue IndexError: list index out of range 각디버그라인은리스트단어를출력하는데,라인을분할 (split)해서 단어로만들때얻어진다.프로그램이실패할때리스트단어는비었다 []. 텍스트 편집기로 파일을 열어 살펴보면 그 지점은 다음과 같다. X-DSPAM-Result: Innocent X-DSPAM-Processed: Sat Jan 5 09:14: X-DSPAM-Confidence: X-DSPAM-Probability: Details: 프로그램이빈라인을만났을때,오류가발생한다.물론,빈라인은 0 단어 ( zero words )다.프로그램을 작성할때,왜이것을생각하지못했 을까?첫단어(word[0])가 From 과 일치하는지코드가점검할때, 인 덱스범위오류(index out of range) 가발생한다. 물론,첫단어가없다면첫단어점검을회피하는 가디언코드(guardian code)를삽입하기최적 장소이기는하다.코드를보호하는방법은많다. 첫단어를살펴보기전에단어의 갯수를확인하는방법을택한다. fhand = open('mbox-short.txt') count = 0 for line in fhand: words = line.split()
122 104 제 8 장. 리스트 (List) # print 'Debug:', words if len(words) == 0 : continue if words[0]!= 'From' : continue print words[2] 변경한코드가실패해서다시디버그할 경우를대비해서, print문을제 거하는대신에print문을주석처리한다.그리고나서,단어가 0 인지를 살펴보고만약 0 이면,파일다음라인으로 건너뛰도록 continue문을 사용하는 가디언문장(guardian statement)을추가한다. 두 개continue문이 흥미롭고 좀더처리가필요한라인집합을정제하 도록돕는 것으로생각할수있다.단어가없는라인은 흥미없어서 다음 라인으로 건너뛴다.첫단어에 From 이없는라인도 흥미없어서 건 너뛴다. 변경된프로그램이성공적으로실행되어서,아마도올바르게 작성된 것 으로 보인다. 가디언 문장(guardian statement)이 words[0]가 정상작동 할 것이라는 것을확인해주지만,충분하지않을수도 있다.프로그램을 작성할때, 무엇이 잘못될수있을까? 를항상생각해야만한다. Exercise 8.2 상기 프로그램의 어느 라인이 여전히 적절하게 보호되지 않 은지를생각해보세요.텍스트파일을구성해서프로그램이실패하도록 만들수있는지살펴보세요.그리고나서,프로그램을변경해서라인이 적절하게보호되게하고,새로운텍스트파일을 잘다룰수있도록시험하 세요. Exercise 8.3 두 if문없이,상기예제의가디언 코드(guardian code) 를다시 작성하세요.대신에단일 if문과 and논리연산자를사용하는복 합 논리 표현식을 사용하세요. 제 15절 용어정의 에일리어싱(aliasing): 하나혹은그이상의변수가동일한 객체를참조하는상 황. 구분자(delimiter): 문자열이 어디서 분할되어져야 할지를 표기하기 위해서 사 용되는문자나문자열. 요소(element): 리스트 혹은 다른 순서(sequence) 값의 하나로 항목(item)이라 고도한다. 동등한(equivalent): 같은 값을 가짐. 인덱스(index): 리스트의 요소를 지칭하는 정수 값. 동일한(identical): 동등을함축하는 같은 객체임. 리스트(list): 순서(sequence) 값. 리스트 운행법(list traversal): 리스트의 각 요소를 순차적으로 접근함.
123 16. 연습문제 105 중첩 리스트(nested list): 또 다른 리스트의 요소인 리스트. 객체(object): 변수가 참조할 수 있는 무엇. 객체는 자료형(type)과 값(value)을 가진다. 참조(reference): 변수와 값의 연관. 제 16절 연습문제 Exercise 파일 사본을 다운로드 받 으세요. romeo.txt파일을열어,한줄씩 읽어들이는프로그램을 작성하세요.각라인 마다분할 (split)함수를사용하여라인을단어리스트로쪼개세요. 각단어마다,단어가 이미리스트에존재하는지를확인하세요.만약단어가리 스트에 없다면, 리스트에 새 단어로 추가하세요. 프로그램이 완료되면, 알파벳 순으로 결과 단어를 정렬하고 출력하세요. Enter file: romeo.txt ['Arise', 'But', 'It', 'Juliet', 'Who', 'already', 'and', 'breaks', 'east', 'envious', 'fair', 'grief', 'is', 'kill', 'light', 'moon', 'pale', 'sick', 'soft', 'sun', 'the', 'through', 'what', 'window', 'with', 'yonder'] Exercise 8.5 전자우편 데이터를 읽어 들이는 프로그램을 작성하세요. From 으로시작하는라인을발견했을때,분할 (split)함수를사용하여라인을단 어로쪼개세요. From 라인의두번째단어,누가메시지를보냈는지에관심이 있다. From Sat Jan 5 09:14: From 라인을파싱하여각 From 라인의두번째단어를출력한다.그리고나 서, From: 이아닌 From 라인갯수를세고,끝에갯수를출력한다. 여기몇줄을삭제한출력예시가 있다. python fromcount.py Enter a file name: mbox-short.txt stephen.marquard@uct.ac.za louis@media.berkeley.edu zqian@umich.edu [...some output removed...] ray@media.berkeley.edu cwen@iupui.edu cwen@iupui.edu cwen@iupui.edu There were 27 lines in the file with From as the first word
124 106 제 8 장. 리스트 (List) Exercise 8.6 사용자가 숫자 리스트를 입력하고, 입력한 숫자 중에 최대값과 최 소값을출력하고사용자가 done 을 입력할때종료하는프로그램을다시 작 성하세요. 사용자가 입력한 숫자를 리스트에 저장하고, max() 과 min() 함수를 사용하여 루프가 끝나면, 최대값과 최소값을 출력하는 프로그램을 작성하세요. Enter a number: 6 Enter a number: 2 Enter a number: 9 Enter a number: 3 Enter a number: 5 Enter a number: done Maximum: 9.0 Minimum: 2.0
125 제 9 장 딕셔너리(Dictionaries) 딕셔너리(dictionary)는 리스트 같지만 좀더 일반적이다. 리스트에서 위치(인텍 스)는 정수이지만, 딕셔너리에서는 인덱스는 임의 자료형(type)이 될 수 있다. 딕셔너리를 인덱스 집합(키(keys)라고 부름)에서 값(value) 집합으로 사상 (mapping)하는 것으로생각할수있다. 각각의키는 값에대응한다.키와 값 을 연관시키는 것을 키-값 페어(key-value pair)라고 부르고, 종종 항목(item) 으로도 부른다. 한예제로,영어단어에서스페인단어에매핑되는사전을만들 것이다.키와 값은모두문자열이다. dict함수는항목이전혀없는사전을신규로생성한다. dict는내장함수명이 어서, 변수명으로 사용하는 것을 피해야 한다. >>> eng2sp = dict() >>> print eng2sp {} 구불구불한괄호 {}는빈딕셔너리를나타낸다.딕셔너리에항목을추가하기 위해서꺾쇠괄호를사용한다. >>> eng2sp['one'] = 'uno' 상기라인은키 one 에서 값'uno'를매핑하는항목을생성한다.딕셔너리를 다시 출력하면, 키와 값 사이에 콜론(:)을 가진 키-값 페어(key-value pair)를 볼 수 있다. >>> print eng2sp {'one': 'uno'} 출력 형식이 또한 입력 형식이다. 예를 들어, 세개 항목을 가진 신규 딕셔너리를 생성할수있다. >>> eng2sp = {'one': 'uno', 'two': 'dos', 'three': 'tres'} eng2sp을출력하면,놀랄 것이다.
126 108 제 9 장. 딕셔너리(Dictionaries) >>> print eng2sp {'one': 'uno', 'three': 'tres', 'two': 'dos'} 키-값페어(key-value pair)순서가 같지않다.사실동일한사례를여러분의 컴 퓨터에서 입력하면,다른 결과를얻게된다. 일반적으로,딕셔너리항목순서는 예측 가능하지않다. 딕셔너리요소가정수 인덱스로색인되지않아서문제되지는않는다.대신에, 키를사용해서상응하는 값을찾을수있다. >>> print eng2sp['two'] 'dos' two 키는항상 값 'dos'에상응되어서딕셔너리항목순서는문제가되지 않는다. 만약 키가 딕셔너리에 존재하지 않으면, 예외 오류가 발생한다. >>> print eng2sp['four'] KeyError: 'four' len함수를딕셔너리에사용해서,키-값페어(key-value pair)항목 개수를반환 한다. >>> len(eng2sp) 3 in연산자도딕셔너리에 작동되는데,어떤 것이딕셔너리키(key)에 있는지알 려준다. (값(value)으로 나타내는 것은 충분히 좋지는 않다.) >>> 'one' in eng2sp True >>> 'uno' in eng2sp False 딕셔너리에무엇이 값으로 있는지확인하기 위해서, values메쏘드를해서리 스트로 값을 반환받고 나서 in 연산자를 사용하여 확인한다. >>> vals = eng2sp.values() >>> 'uno' in vals True in연산자는리스트와딕셔너리에 각기다른알고리즘을사용한다.리스트에 대해서선형 검색알고리즘을사용한다.리스트가길어짐에따라 검색시간은 리스트길이에비례하여길어진다.딕셔너리에대해서파이썬은해쉬테이블 (hash table)로불리는놀라운특성을 가진알고리즘을사용한다.얼마나많은 항목이딕셔너리에 있는지에관계없이 in연산자는대략동일한시간이소요 된다. 왜 해쉬 함수가 마술 같은지에 대해서는 설명하지 않지만, wikipedia. org/wiki/hash_table 에서 좀더 많은 정보를 얻을 수 있다. Exercise 9.1 words.txt 단어를 읽어서 딕셔너리에 키로 저장하는 프로그램을 작성하세요.값이무엇이든지상관없습니다.딕셔너리에문자열을확인하는가 장빠른방법으로in연산자를사용할수있습니다.
127 1. 계수기(counter)집합으로서딕셔너리 109 제 1 절 계수기(counter) 집합으로서 딕셔너리 문자열이주어진상태에서, 각문자가얼마나나타나는지를센다고 가정합시다. 몇 가지방법이아래에 있습니다 개변수를알파벳문자 각각에대해생성한다.그리고나서아마도연쇄 조건문을사용하여문자열을훑고해당 계수기(counter)를하나씩증가 한다 개요소를 가진리스트를생성한다.내장함수 ord를사용해서 각문자 를숫자로변환한다.리스트안에 인덱스로숫자를사용해서적당한 계수 기(counter)를 증가한다. 3. 키(key)로 문자, 계수기(counter)로 해당 값(value)을 갖는 딕셔너리를 생 성한다.처음문자를만나면,딕셔너리에항목으로추가한다.추가한후에 는기존항목 값을증가한다. 상기 3개옵션은동일한연산을수행하지만, 각각은다른방식으로연산을구현 한다. 구현(implementation)은 연산(computation)을 수행하는 방법이다. 어떤 구현 방법이다른 것보다낫다.예를들어,딕셔너리구현의 장점은사전에문자열에 서어떤문자가나타날지몰라도된다.다만나타날문자에대한 공간만준비하 면된다는 것이다. 다음에 딕셔너리로 구현한 코드가 있다. word = 'brontosaurus' d = dict() for c in word: if c not in d: d[c] = 1 else: d[c] = d[c] + 1 print d 계수기(counter)혹은빈도에대한통계용어인히스토그램(histogram)을효과 적으로 계산해보자. for루프는문자열을훑는다.매번루프를반복할때마다딕셔너리에문자 c가 없다면,키c와초기값 1을 가진새로운항목을생성한다.문자c가 이미딕셔너 리에존재한다면,d[c]을증가한다. 다음프로그램실행 결과가 있다. {'a': 1, 'b': 1, 'o': 2, 'n': 1, 's': 2, 'r': 2, 'u': 2, 't': 1} 히스토그램은문자 a,'b'는 1회,'o'는 2회등등나타남을보여준다. 딕셔너리에는키와디폴트(default) 값을 갖는 get메쏘드가 있다.딕셔너리에 키가나타나면, get메쏘드는해당 값을반환하고,해당 값이없으면디폴트 값 을반환한다.예를들어,
128 110 제 9 장. 딕셔너리(Dictionaries) >>> counts = { 'chuck' : 1, 'annie' : 42, 'jan': 100} >>> print counts.get('jan', 0) 100 >>> print counts.get('tim', 0) 0 get메쏘드를사용해서상기히스토그램루프를좀더 간결하게 작성할수있 다. get메쏘드는딕셔너리에키가존재하지않는 경우를 자동적으로다루기 때문에,if문을없애 4줄을 1줄로줄일수있다. word = 'brontosaurus' d = dict() for c in word: d[c] = d.get(c,0) + 1 print d 계수기(counter)루프를단순화하려고get메쏘드를사용하는 것은파이썬에서 흔히사용되는 숙어(idiom) 가되고,책후반부까지많이사용할 것이다.시 간을 가지고서 잠시 if문과 in연산자를사용한루프와 get메쏘드를사용한 루프를비교해보세요.동일한연산을수행하지만,하나가더간결한다. 제 2절 딕셔너리와파일 딕셔너리의 흔한 사용법 중의 하나는 텍스트로 작성된 파일에 단어 빈 도를 세는 것이다. romeoandjuliet/romeo_juliet.2.2.html 사이트 덕분에 로미오와 쥴리엣(Romeo and Juliet)텍스트파일에서시작합시다. 처음연습으로구두점이없는짧고 간략한텍스트버젼을사용한다.나중에구 두점이포함된전체텍스트로 작업할 것이다. But soft what light through yonder window breaks It is the east and Juliet is the sun Arise fair sun and kill the envious moon Who is already sick and pale with grief 파일라인을 읽고, 각라인을단어리스트로쪼개고,루프를돌려사전을 이용하 여 각 단어의 빈도수를 세는 파이썬 프로그램을 작성한다. 두 개의for루프를사용한다.외곽루프는파일라인을 읽고,내부루프는특정 라인의단어 각각에대해반복한다.하나의루프는외곽 루프가되고,또다른 루프는 내부 루프가 되어서 중첩 루프(nested loops)라고 불리는 패턴 사례다. 외곽루프가한번반복을할때마다내부루프는모든반복을수행하기때문 에내부루프는 좀더빨리 반복을수행하고외곽루프는좀더천천히반복을 수행하는 것으로생각할수있다. 두중첩루프의조합이 입력파일의모든라인에 있는모든단어의빈도를 계수 (count)하도록 보증합니다.
129 3. 반복과딕셔너리 111 fname = raw_input('enter the file name: ') try: fhand = open(fname) except: print 'File cannot be opened:', fname exit() counts = dict() for line in fhand: words = line.split() for word in words: if word not in counts: counts[word] = 1 else: counts[word] += 1 print counts 프로그램을실행하면,정렬되지않은해쉬순서로모든단어의빈도수를출력 합니다. romeo.txt 파일은 다운 로드 가능하다. python count1.py Enter the file name: romeo.txt {'and': 3, 'envious': 1, 'already': 1, 'fair': 1, 'is': 3, 'through': 1, 'pale': 1, 'yonder': 1, 'what': 1, 'sun': 2, 'Who': 1, 'But': 1, 'moon': 1, 'window': 1, 'sick': 1, 'east': 1, 'breaks': 1, 'grief': 1, 'with': 1, 'light': 1, 'It': 1, 'Arise': 1, 'kill': 1, 'the': 3, 'soft': 1, 'Juliet': 1} 가장높은빈도단어와빈도수를찾기 위해서딕셔너리를훑는 것이불편하다. 좀더 도움이 되는 출력결과를 만들려고 파이썬 코드를 추가하자. 제 3절 반복과딕셔너리 for문에 순서(sequence)로서 딕셔너리를 사용한다면, 딕셔너리 키를 훑는다. 루프는 각키와해당 값을출력한다. counts = { 'chuck' : 1, 'annie' : 42, 'jan': 100} for key in counts: print key, counts[key] 출력은다음과 같다. jan 100 chuck 1 annie 42 다시 한번, 키는 특별한 순서가 없다. 이패턴을사용해서앞서기술한다양한루프숙어를구현한다.예를들어,딕셔 너리에서 10보다큰값을 가진항목을모두찾고자한다면,다음과 같이코드를 작성한다.
130 112 제 9 장. 딕셔너리(Dictionaries) counts = { 'chuck' : 1, 'annie' : 42, 'jan': 100} for key in counts: if counts[key] > 10 : print key, counts[key] for루프는딕셔너리키(keys)를반복한다.그래서, 인덱스연산자를사용해서 각키에상응하는 값(value)을 가져와야한다.여기출력값이 있다. jan 100 annie 이상 값만 가진항목만볼수있다. 알파벳순으로키를출력하고자한다면,딕셔너리 객체의 keys메쏘드를사용 해서딕셔너리키리스트를생성한다.그리고나서리스트를정렬하고,정렬된 리스트를루프돌리고,아래와 같이정렬된순서로키/값페어(key/value pair) 를출력한다. counts = { 'chuck' : 1, 'annie' : 42, 'jan': 100} lst = counts.keys() print lst lst.sort() for key in lst: print key, counts[key] 다음에출력결과가 있다. ['jan', 'chuck', 'annie'] annie 42 chuck 1 jan 100 처음에 keys메쏘드로부터얻은정렬되지않은키리스트가 있고,그리고나서 for루프로정렬된키/값페어(key/value pair)가 있다. 제 4절 고급텍스트파싱 romeo.txt 파일을 사용한 상기 예제에서, 수작업으로 모든 구두점을 제거해서 가능한단순하게만들었다.실제텍스트는아래보여지는 것처럼많은구두점이 있다. But, soft! what light through yonder window breaks? It is the east, and Juliet is the sun. Arise, fair sun, and kill the envious moon, Who is already sick and pale with grief, 파이썬 split함수는 공백을찾고 공백으로구분되는토큰으로단어를처리하 기때문에, soft! 와 soft 는다른단어로처리되고 각단어에대해서별도 딕셔너리항목을생성한다. 파일에대문자가 있어서, who 와 Who 를다른단어,다른빈도수를 가진 것으로 처리한다.
131 4. 고급 텍스트 파싱 113 lower, punctuation, translate 문자열 메쏘드를 사용해서 상기 문제를 해결 할수있다. translate메쏘드가 가장적합하다. translate메쏘드에대한문 서가다음에 있다. string.translate(s, table[, deletechars]) (만약존재한다면) deletechars에있는모든문자를삭제한다.그리고나서순서 수(ordinal)로 색인된 각 문자를 번역하는 256-문자열 테이블(table)을 사용해서 문자를번역한다.만약테이블이 None 이면,문자삭제단계만수행된다. table을명세하지는않을 것이고, deletechars매개변수를사용해서모든구 두점을삭제할 것이다.파이썬이 구두점 으로 간주하는문자리스트를출력하 게할것이다. >>> import string >>> string.punctuation }~' 프로그램을다음과 같은수정을한다. import string # 신규 코드 fname = raw_input('enter the file name: ') try: fhand = open(fname) except: print 'File cannot be opened:', fname exit() counts = dict() for line in fhand: line = line.translate(none, string.punctuation) line = line.lower() words = line.split() for word in words: if word not in counts: counts[word] = 1 else: counts[word] += 1 # 신규 코드 # 신규 코드 print counts translate메쏘드를사용해서모든구두점을제거했고, lower메쏘드를사 용해서라인을소문자로수정했다.나머지프로그램은변경된게없다.파이썬 2.5 이전버젼에는 translate메쏘드가첫매개변수로 None을받지않아서 translate 메쏘드를 호출하기 위해서 다음 코드를 사용하세요. print a.translate(string.maketrans(' ',' '), string.punctuation "파이썬 예술(Art of Python) 혹은 파이썬스럽게 생각하기(Thinking Pythonically) 를배우는 일부분은파이썬은흔한 자료분석문제에대해서내 장기능을 가지고 있는 것을깨닫는 것이다.시간이지남에따라,충분한예제 코드를보고충분한문서를 읽는다. 작업을편하게할수있게 이미다른사람이
132 114 제 9 장. 딕셔너리(Dictionaries) 작성한코드가존재하는지를살펴보기 위해서어디를찾아봐야하는지도알게 될 것이다. 다음은출력결과의축약버젼이다. Enter the file name: romeo-full.txt {'swearst': 1, 'all': 6, 'afeard': 1, 'leave': 2, 'these': 2, 'kinsmen': 2, 'what': 11, 'thinkst': 1, 'love': 24, 'cloak': 1, a': 24, 'orchard': 2, 'light': 5, 'lovers': 2, 'romeo': 40, 'maiden': 1, 'whiteupturned': 1, 'juliet': 32, 'gentleman': 1, 'it': 22, 'leans': 1, 'canst': 1, 'having': 1,...} 출력결과는 여전히 다루기 힘들어 보입니다. 파이썬을 사용해서 정확히 찾고자 는하는 것을찾았으나파이썬튜플(tuples)에대해서학습할필요성을느껴진 다.튜플을학습할때,다시 이예제를살펴볼 것이다. 제 5절 디버깅 점점더큰데이터로 작업함에따라,수작업으로데이터를확인하거나출력을 통해서디버깅을하는 것이어려울수있다.큰데이터를디버깅하는몇가지 방법이 있다. 입력값을 줄여라(Scale down the input): ] 가능하면, 데이터 크기를 줄여라. 예 를들어,프로그램이텍스트파일을 읽는다면,첫10줄로시작하거나,찾 을수있는 작은예제로시작하라.데이터파일을편집하거나,프로그램을 수정해서첫n라인만 읽도록프로그램을변경하라. 오류가 있다면, n을줄여서오류를 재현하는 가장 작은 값으로만들어라. 그리고 나서, 오류를 찾고 수정해 나감에 따라 점진적으로 늘려나가라. 요약값과 자료형을확인하라(Check summaries and types): 전체데이터를출 력하고 검증하는대신에데이터를요약하여출력하는 것을생각하라:예 를들어,딕셔너리항목의숫자혹은리스트숫자의총계 실행 오류(runtime errors)의 일반적인 원인은 올바른 자료형(right type) 이아니기때문이다. 이런종류의오류를디버깅하기 위해서,종종 값의 자료형을 출력하는 것으로 충분하다. 자가 진단 작성(Write self-checks): 종종 오류를 자동적으로 검출하는 코드를 작성한다.예를들어,리스트숫자의평균을 계산한다면, 결과값은리스 트의 가장큰값보다클수없고, 가장 작은 값보다 작을수없다는 것을 확인할수있다. 완전히비상식적인 결과를탐지하기때문에 건전성 검사(sanity check) 라고부른다. 또다른 검사법은두가지다른연산의 결과를비교해서 일치하는지살펴 보는 것이다. 일치성 검사(consistency check) 라고부른다. 고급 출력(Pretty print the output): 디버깅 출력결과를 서식화하는 것은 오류 발견을용이하게한다. 다시한번,발판(scaffolding)을만드는데들인시간이디버깅에소비되는시간 을줄일수있다.
133 6. 용어정의 115 제 6절 용어정의 딕셔너리(dictionary): 키(key)에서 해당 값으로 매핑(mapping) 해쉬테이블(hashtable): 파이썬 딕셔너리를 구현하기 위해 사용된 알고리즘 해쉬 함수(hash function): 키에 대한 위치를 계산하기 위해서 해쉬테이블에서 사용되는 함수 히스토그램(histogram): 계수기(counter)집합. 구현(implementation): 연산(computation)을 수행하는 방법 항목(item): 키-값 페어(key-value pair)에 대한 또 다른 이름. 키(key): 키-값 페어(key-value pair)의 첫번째 부분으로 딕셔너리에 나타나는 객체. 키-값 페어(key-value pair): 키에서 값으로 매핑 표현. 룩업(lookup): 키를 가지고 해당 값을 찾는 딕셔너리 연산. 중첩루프(nested loops): 루프 내부 에하나혹은그이상의루프가 있음.외곽 루프가 1회실행될때,내부루프는전체반복을완료함. 값(value): 키-값 페어(key-value pair)의 두번째 부분으로 딕셔너리에 나타나 는 객체. 앞에서 사용한 단어 값(value) 보다 더 구체적이다. 제 7절 연습문제 Exercise 9.2 커밋(commit)이 무슨 요일에 수행되었는지에 따라 전자우편 메세 지를구분하는프로그램을 작성하세요. From 으로시작하는라인을찾고, 3 번째 단어를 찾아서 요일별 횟수를 계수(count)하여 저장하세요. 프로그램 끝에 딕셔너리 내용을 출력하세요. (순서는 문제가 되지 않습니다.) Sample Line: From stephen.marquard@uct.ac.za Sat Jan 5 09:14: Sample Execution: python dow.py Enter a file name: mbox-short.txt {'Fri': 20, 'Thu': 6, 'Sat': 1} Exercise 9.3 전자우편 로그(log)를 읽고, 히스토그램을 생성하는 프로그램을 작성하세요.딕셔너리를사용해서전자우편주소별로얼마나많은전자우편이 왔는지를 계수(count)하고 딕셔너리를 출력합니다. Enter file name: mbox-short.txt {'gopal.ramasammycook@gmail.com': 1, 'louis@media.berkeley.edu': 3, 'cwen@iupui.edu': 5, 'antranig@caret.cam.ac.uk': 1, 'rjlowe@iupui.edu': 2, 'gsilver@umich.edu': 3,
134 116 제 9 장. 딕셔너리(Dictionaries) 'david.horwitz@uct.ac.za': 4, 'wagnermr@iupui.edu': 1, 'zqian@umich.edu': 4, 'stephen.marquard@uct.ac.za': 2, 'ray@media.berkeley.edu': 1} Exercise 9.4 상기프로그램에누가가장많은전자우편메시지를가졌는지알 아내는 코드를 추가하세요. 결국,모든데이터를 읽고,딕셔너리를생성한다.최대루프(장 7.2참조)를사용 해서딕셔너리를훑어서누가가장많은전자우편메시지를갖는지,그리고그 사람이 얼마나 많은 메시지를 갖는지 출력한다. Enter a file name: mbox-short.txt cwen@iupui.edu 5 Enter a file name: mbox.txt zqian@umich.edu 195 Exercise 9.5 다음프로그램은주소대신에도메인 이름을기록한다.누가메 일을보냈는지대신(즉,전체전자우편주소)메시지가어디에서부터왔는지 출처를 기록한다. 프로그램 마지막에 딕셔너리 내용을 출력한다. python schoolcount.py Enter a file name: mbox-short.txt {'media.berkeley.edu': 4, 'uct.ac.za': 6, 'umich.edu': 7, 'gmail.com': 1, 'caret.cam.ac.uk': 1, 'iupui.edu': 8}
135 제 10 장 튜플(Tuples) 제 1절 튜플은불변이다. 튜플(tuple) 1 은리스트와마찬가지로순서(sequence) 값이다.튜플에저장된 값 은 임의 자료형(type)이될수있고,정수로색인된다.중요한차이점은튜플은 불변(immutable)하다는 것이다. 튜플은 또한 비교 가능(comparable)하고 해 쉬형(hashable)이다.따라서,리스트 값을정렬할수있고,파이썬딕셔너리키 값으로튜플을사용할수있다. 구문론적으로, 튜플은 콤마로 구분되는 리스트 값이다. >>> t = 'a', 'b', 'c', 'd', 'e' 꼭필요하지는않지만,파이썬코드를봤을때, 가독성을높여튜플을빠르게 알아볼수있도록괄호로튜플을 감싸는 것이 일반적이다. >>> t = ('a', 'b', 'c', 'd', 'e') 단일요소를 가진튜플을생성하기 위해서마지막콤마를포함해야한다. >>> t1 = ('a',) >>> type(t1) <type 'tuple'> 콤마가없는 경우파이썬에서는 ('a')을괄호를 가진문자열표현으로 간주하 여문자열로평가한다. >>> t2 = ('a') >>> type(t2) <type 'str'> 튜플을구축하는다른방법은내장함수tuple을사용하는 것이다. 인자가없는 경우,빈튜플을생성한다. 1 재미난사실:단어 튜플(tuple) 은가변길이 (한배,두배,세배,네배,다섯배,여섯배, 일곱배 등) 숫자열에 붙여진 이름에서 유래한다.
136 118 제 10 장. 튜플(Tuples) >>> t = tuple() >>> print t () 만약 인자가문자열,리스트혹은튜플 같은순서(sequence)인 경우, tuple에 호출한 결과는 요소 순서(sequence)를 가진 튜플이 된다. >>> t = tuple('lupins') >>> print t ('l', 'u', 'p', 'i', 'n', 's') 튜플(tuple)이 생성자 이름이기 때문에 변수명으로 튜플 사용을 피해야 한다. 대부분의리스트연산자는튜플에서도사용 가능하다.꺾쇠연산자가요소를 색인한다. >>> t = ('a', 'b', 'c', 'd', 'e') >>> print t[0] 'a' 그리고, 슬라이스 연산자(slice operator)는 요소 범위를 선택한다. >>> print t[1:3] ('b', 'c') 하지만,튜플요소중하나를변경하고하면,오류가발생한다. >>> t[0] = 'A' TypeError: object doesn't support item assignment 튜플요소를변경할수는없지만,튜플을다른튜플로교체는할수있다. >>> t = ('A',) + t[1:] >>> print t ('A', 'b', 'c', 'd', 'e') 제 2절 튜플비교하기 비교연산자는튜플과다른순서(sequence)와함께쓸수있다.파이썬은 각순 서(sequence)에서비교를첫요소부터시작한다.만약두요소가 같다면,다음 요소비교를진행하며서로다른요소를찾을때까지 계속한다.후속요소가 아무리큰값이라고하더라도비교 고려대상에서제외된다. >>> (0, 1, 2) < (0, 3, 4) True >>> (0, 1, ) < (0, 3, 4) True 정렬 (sort)함수도동일한방식으로동작한다.첫요소를먼저정렬하지만,동 일한 경우두번째요소를정렬하고,그후속요소를동일한방식으로정렬한다. 이기능이다음 DSU라고불리는패턴이된다.
137 3. 튜플대입(Tuple Assignment) 119 데코레이트 (Decorate) : 순서(sequence)에서 요소 앞에 하나 혹은 그 이상의 키를 가진 튜플 리스트를 구축해서 순서(sequence)를 장식한다. 정렬 (Sort) :파이썬내장함수sort를사용한튜플리스트를정렬한다. 언데코레이트 (Undecorate) : 순서(sequence)의 정렬된 요소만 추출하여 장식 을지웁니다. 예를들어,단어리스트가 있고 가장긴단어부터 가장짧은단어순으로정렬한 다고 가정하자. txt = 'but soft what light in yonder window breaks' words = txt.split() t = list() for word in words: t.append((len(word), word)) t.sort(reverse=true) res = list() for length, word in t: res.append(word) print res 첫번째루프는튜플리스트를생성하고, 각튜플은단어앞에길이정보를 가 진다. 정렬(sort)함수는첫번째요소,길이를우선비교하고,동률일 경우에만두번 째 요소를 고려한다. 정렬(sort) 함수의 인자 reverse=true는 내림차순으로 정렬한다는 의미다. 두번째루프는튜플리스트를운행하여훑고,길이에따라내림차순으로단어 리스트를생성한다.그래서, 5문자단어는역알파벳순으로정렬되어 있다. 다음리스트에서 what 이 soft 보다앞에나타난다. 프로그램의출력은다음과 같다. ['yonder', 'window', 'breaks', 'light', 'what', 'soft', 'but', 'in'] 물론,파이썬리스트로변환하여내림차순으로정렬된문장은시적인 의미를 많이 잃어버렸다. 제 3 절 튜플 대입(Tuple Assignment) 파이썬언어의독특한구문론적인기능중의하나는대입문의왼편에튜플을놓 을수있다는 것이다.왼편이순서(sequence)인 경우한번에하나 이상의변수에 대입할수있다. 다음예제에서,순서(sequence)인두개요소를 갖는리스트가 있다.하나의문 장으로 순서(sequence)의 첫번째와 두번째 요소를 변수 x와 y에 대입한다.
138 120 제 10 장. 튜플(Tuples) >>> m = [ 'have', 'fun' ] >>> x, y = m >>> x 'have' >>> y 'fun' >>> 마술이아니다.파이썬은대략튜플대입구문을다음과 같이해석한다. 2 >>> m = [ 'have', 'fun' ] >>> x = m[0] >>> y = m[1] >>> x 'have' >>> y 'fun' >>> 스타일적으로대입문왼편에튜플을사용할때,괄호를생략한다.하지만다음 은동일하게적합한구문이다. >>> m = [ 'have', 'fun' ] >>> (x, y) = m >>> x 'have' >>> y 'fun' >>> 튜플대입문을사용하는특히똑똑한 응용사례는단일문장으로두변수 값을 교환(swap)하는 것이다. >>> a, b = b, a 양쪽문장이모두튜플이지만,왼편은튜플변수이고오른편은튜플표현식이 다.오른편 각각의 값이왼편해당변수에대입된다.대입이 이루어지기전에 오른편의모든표현식이평가된다. 왼편의 변수 갯수와 오른편의 값의 갯수는 동일해야 한다. >>> a, b = 1, 2, 3 ValueError: too many values to unpack 좀더 일반적으로,오른편은 임의순서(문자열,리스트혹은튜플)가될수있다. 예를들어,전자우편주소를사용자 이름과도메인으로분할하기 위해서다음과 같이프로그램을 작성할수있다. >>> addr = 'monty@python.org' >>> uname, domain = addr.split('@') 2 파이썬은구문을문자그대로해석하지는않는다.예를들어,동일한것을딕셔너리로 작성 한다면, 기대한 것처럼 동작하지는 않는다.
139 4. 딕셔너리와 튜플 121 분할 (split)함수로부터반환되는 값은두개요소를 가진리스트다.첫번째 요소는 uname에 두번째 요소는 domain에 대입된다. >>> print uname monty >>> print domain python.org 제 4절 딕셔너리와튜플 딕셔너리에는튜플리스트를반환하는 items메쏘드가 있다. 각튜플은키-값 페어(key-value pair)다. 3 >>> d = {'a':10, 'b':1, 'c':22} >>> t = d.items() >>> print t [('a', 10), ('c', 22), ('b', 1)] 딕셔너리로부터기대했듯이,항목은특별한순서가없다. 하지만튜플리스트는리스트여서비교가 가능하기때문에,튜플리스트를정 렬할수있다.딕셔너리를튜플리스트로변환하는 것이키로정렬된딕셔너리 내용을출력할수있게한다. >>> d = {'a':10, 'b':1, 'c':22} >>> t = d.items() >>> t [('a', 10), ('c', 22), ('b', 1)] >>> t.sort() >>> t [('a', 10), ('b', 1), ('c', 22)] 새로운리스트는키값으로오름차순알파벳순으로정렬된다. 제 5절 딕셔너리로다중대입 items함수,튜플대입, for문을조합해서,단일루프로딕셔너리의키와 값을 운행하여훑는멋진코드패턴을만들수있다. for key, val in d.items(): print val, key 상기 루프에는 두개의 반복 변수(iteration variables)가 있다. items 함수가 튜 플 리스트를 반환하고, key, val는 튜플 대입하여 딕셔너리에 있는 각각의 키- 값페어(key-value pair)를성공적으로반복한다. 매번루프를반복할때마다,key와 value는딕셔너리(여전히해쉬순으로되어 있음)의다음키-값페어(key-value pair)로진행한다. 3 파이썬 3.0으로가면서살짝달라졌다.
140 122 제 10 장. 튜플(Tuples) 루프의출력결과는다음과 같다. 10 a 22 c 1 b 다시한번해쉬키순서다. (즉,특별한순서가없다.) 두기술을조합하면,딕셔너리내용을키-값페어(key-value pair)에저장된 값 의순서로정렬하여출력할수있다. 이것을수행하기 위해서, 각튜플이 (value, key)형태인튜플리스트를 작성 한다. items메쏘드를사용하여리스트 (key, value)튜플을만든다.하지만 이번에는키가아닌 값으로정렬한다.키-값(key-value)튜플리스트를생성하 면, 역순으로 리스트를 정렬하고 새로운 정렬 리스트를 출력하는 것은 쉽다. >>> d = {'a':10, 'b':1, 'c':22} >>> l = list() >>> for key, val in d.items() :... l.append( (val, key) )... >>> l [(10, 'a'), (22, 'c'), (1, 'b')] >>> l.sort(reverse=true) >>> l [(22, 'c'), (10, 'a'), (1, 'b')] >>> 조심스럽게 각튜플첫번째요소로 값(value)을 갖는튜플리스트를생성했다. 튜플 리스트를 정렬하여 값으로 정렬된 딕셔너리가 생성되었다. 제 6절 가장빈도수가높은단어 로미오와쥴리엣 2장 2막텍스트파일로다시돌아와서,텍스트에서 가장빈도 수가높은단어를 10개를출력하기 위해서상기학습한기법을사용하여프로 그램을보강해보자. import string fhand = open('romeo-full.txt') counts = dict() for line in fhand: line = line.translate(none, string.punctuation) line = line.lower() words = line.split() for word in words: if word not in counts: counts[word] = 1 else: counts[word] += 1 # Sort the dictionary by value lst = list()
141 7. 딕셔너리 키로 튜플 사용하기 123 for key, val in counts.items(): lst.append( (val, key) ) lst.sort(reverse=true) for key, val in lst[:10] : print key, val 파일을 읽고 각단어를문서의단어빈도수에매핑(사상)하여딕셔너리를 계산 하는프로그램첫부분은바뀌지않는다.하지만, counts를단순히출력하는 대신에(val, key) 튜플 리스트를 생성하고 역순으로 리스트를 정렬한다. 값이첫위치에 있기때문에,비교목적으로 값을사용한다.만약동일한 값을 가 진튜플이하나이상존재한다면,두번째요소(키, key)를살펴본다.그래서 값이 동일한 경우키의알파벳순으로추가정렬된다. 마지막에다중대입반복을수행하는멋진for루프를 작성한다.그리고,리스트 슬라이스(lst[:10])를통해 가장빈도수가높은상위 10개단어를출력한다. 이제단어빈도분석을 위해서 작성한프로그램의마지막출력결과는원하는 바를완수한 것처럼보인다. 61 i 42 and 40 romeo 34 to 34 the 32 thou 32 juliet 30 that 29 my 24 thee 복잡한데이터파싱과분석 작업이 이해하기쉬운 19줄파이썬프로그램으로 수행된사실이왜파이썬이정보탐색언어로서좋은선택인지보여준다. 제 7절 딕셔너리키로튜플사용하기 튜플은 해쉬형(hashable)이고, 리스트는 그렇지 못하기 때문에, 만약 딕셔너리 에 사용할 복합(composite)키를 생성하려면, 키로 튜플을 사용해야 한다. 만약 성(last-name)과 이름(first-name)을 가지고 전화번호에 사상(매핑, mapping)하는 전화번호부를 생성하려고 하면, 복합키와 마주친다. 변수 last, first, number을정의했다고 가정하면,다음과 같이딕셔너리대입문을 작성 할수있다. directory[last,first] = number 꺾쇠괄호표현은튜플이다.딕셔너리를훑기 위해서 for루프에튜플대입을 사용한다.
142 124 제 10 장. 튜플(Tuples) for last, first in directory: print first, last, directory[last,first] 상기루프가튜플인 directory에키를훑는다. 각튜플요소를 last, first에 대입하고나서, 이름과해당전화번호를출력한다. 제 8절 순서(sequence) :문자열,리스트,튜플 여기서리스트튜플에초점을맞추었지만, 이장의 거의모든예제가또한리 스트의리스트,튜플의튜플,리스트튜플에도동작한다. 가능한모든조합을 열거하는 것을 피하기 위해서, 순서의 순서(sequences of sequences)에 대해서 논의하는 것이 때로는 쉽다. 대부분의문맥에서다른종류의순서(문자열,리스트,튜플)는상호호환해서 사용될수있다.그런데왜그리고어떻게다른 것보다 이것을선택해야될까? 명확한 것부터 시작하자. 문자열은 요소가 문자여야 하기 때문에 다른 순서(sequence)보다 제약이 따른다. 또한 문자열은 불변(immutable)이다. 새로운 문자 열을생성하는 것과반대로,문자열에 있는문자를변경하고자한다면,대신에 문자리스트를사용하는 것을생각할수있다. 리스트는 튜플보다 좀더 일반적으로 사용된다. 이유는 대체로 변경가능(mutable)하기때문이다.하지만,다음몇가지 경우에튜플이좀더선호된다. 1. return 문처럼 어떤 맥락에서, 리스트보다 튜플을 생성하는 것이 구문론 적으로더간략하다.다른맥락에서는리스트가더선호될수있다. 2. 딕셔너리 키로서 순서(sequence)를 사용하려면, 튜플이나 문자열같은 불 변 자료형(immutable type)을사용해야한다. 3. 함수에 인자로순서(sequence)를전달하려면,튜플을사용하는 것이에 일리어싱(aliasing)으로생기는예기치못한행동에대한 가능성을줄여 준다. 튜플은 불변(immutable)이어서, 기존 리스트를 변경하는 sort, reverse 같은 메쏘드를 제공하지는 않는다. 하지만, 파이썬이 제공하는 내장함수 sorted, reversed를통해서,매개변수로 임의순서(sequence)를전달받아서, 같은 요소를다른순서로정렬된새로운리스트를반환한다. 제 9절 디버깅 리스트, 딕셔너리, 튜플은 자료 구조(data structures)로 일반적으로 알려져 있 다. 이번장에서리스트튜플,키로튜플, 값으로리스트를담고 있는딕셔너리 같은복합 자료구조를보기시작했다.복합 자료구조는 유용하지만,저자가 작명한모양오류(shape errors)라고불리는오류에노출되어 있다.즉, 자료
143 9. 디버깅 125 구조가 잘못된 자료형(type),크기,구성일 경우오류가발생한다.혹은코드를 작성하고, 자료의모양이생각나지않는 경우도오류의원인이된다. 예를들어,정수하나를 가진리스트를기대하고, (리스트가아닌) 일반정수를 넘긴다면, 작동하지않는다. 프로그램을디버깅할때,정말어려운버그를 잡으려고 작업을한다면,다음네 가지를시도할수있다. 코드 읽기(reading): 코드를면밀히조사하고,스스로에게다시 읽어주고,코 드가 자신이 작성한 의도를담고 있는지점검하라. 실행(running): 변경해서다른버젼을실행해서실험하라.종종,프로그램이적 절한 곳에 적절한 것을 보여준다면, 문제가 명확하다. 발판(scaffolding)을 만들기 위해서때때로시간을들일필요도 있다. 반추(ruminating): 생각의시간을 갖자.어떤종류의오류인가:구문,실행, 의 미론(semantic). 오류 메시지로부터 혹은 프로그램 출력결과로부터 무슨 정보를얻을수있는가?어떤종류오류가지금보고 있는문제를만들었 을까?문제가나타나기전에,마지막으로변경한 것은무엇인가? 퇴각(retreating): 어느시점에선가,최선은물러서서,최근의변경을다시원 복하는 것이다. 잘동작하고 이해하는프로그램으로다시돌아가서,다시 프로그램을 작성한다. 초보프로그래머는종종 이들활동중하나에사로잡혀다른 것을 잊곤한다. 활동 각각은 고유한실패방식과함께온다. 예를들어,프로그램을정독하는 것은문제가 인쇄상의오류에 있다면도움이 되지만,문제가 개념상오해에뿌리를두고 있다면그다지도움이되지못한다. 만약 작성한프로그램을 이해하지못한다면, 100번 읽을수는 있지만,오류를 발견할수는없다.왜냐하면,오류는여러분머리에 있기때문입니다. 만약 작고 간단한테스트를진행한다면,실험을수행하는 것이도움이될수 있다.하지만,코드를 읽지않거나,생각없이실험을수행한다면,프로그램이 작동될때까지무작위변경하여 개발하는 랜덤워크프로그램(random walk programming) 패턴에빠질수있다.말할필요없이랜덤워크프로그래밍은 시간이오래 걸린다. 생각할시간을 가져야한다.디버깅은실험 과학 같은 것이다.문제가무엇인지 에대한최소한한가지 가설을 가져야한다.만약두개혹은그이상의 가능성이 있다면, 이러한 가능성중에서하나라도줄일수있는테스트를생각해야한다. 휴식시간을 가지는 것은생각하는데도움이된다.대화를하는 것도도움이된 다.문제를다른사람혹은 자신에게도설명할수있다면,질문을마치기도전에 답을종종발견할수있다. 하지만,오류가너무많고수정하려는코드가매우크고,복잡하다면최고의디 버깅기술도무용지물이다. 가끔,최선의선택은퇴각하는 것이다. 작동하고 이 해하는 곳까지 후퇴해서 프로그램을 간략화하라.
144 126 제 10 장. 튜플(Tuples) 초보프로그래머는종종퇴각하기를꺼려한다.왜냐하면,설사 잘못되었지만, 한줄코드를지울수없기때문이다.삭제하지않는 것이기분을좋게한다면, 다시 작성하기전에프로그램을다른파일에복사하라.그리고나서,한번에조 금씩 붙여넣어라. 정말어려운버그(hard bug)를발견하고 고치는 것은코드 읽기,실행,반추,때 때로퇴각을요구한다.만약 이들활동중하나도먹히지않는다면,다른 것들을 시도해 보세요. 제 10절 용어정의 비교가능한(comparable): 동일한 자료형의 다른 값과 비교하여 큰지, 작은지, 혹은 같은지를확인하기 위해서확인할수있는 자료형(type).비교가능한 (comparable) 자료형은 리스트에 넣어서 정렬할 수 있다. 자료구조(data structure): 연관된 값의집합,종종리스트,딕셔너리,튜플등 으로 조직화된다. DSU: decorate-sort-undecorate, 의 약어로 리스트 튜플을 생성, 정렬, 결과 일부 추출을 포함하는 패턴. 모음(gather): 가변-길이 인자튜플을조합하는연산. 해쉬형(hashable): 해쉬 함수를 가진 자료형(type). 정수, 소수점, 문자열 같은 불변형은해쉬형이다.리스트나딕셔너리처럼변경가능한형은해쉬형 이아니다. 스캐터(scatter): 순서(sequence)를 리스트 인자로 다루는 연산. (자료구조의)모양 (shape (of a data structure)): 자료 구조의 자료형(type), 크기,구성을요약. 싱글톤(singleton): 단일 요소를 가진 리스트 (혹은 다른 순서(sequence)). 튜플(tuple): 불변 요소들의 순서 (sequence). 튜플 대입(tuple assignment): 오른편 순서(sequence)와 왼편 튜플 변수를 대 입.오른편이평가되고나서 각요소들은왼편의변수에대입된다. 제 11절 연습문제 Exercise 10.1 앞서 작성한 프로그램을 다음과 같이 수정하세요. From 라인을 읽고파싱하여라인에서주소를뽑아내세요.딕셔너리를사용하여각사람으로 부터 메시지 숫자를 계수(count)한다. 모든데이터를 읽은후에가장많은커밋(commit)을한사람을출력하세요.딕셔 너리로부터리스트 (count, )튜플을생성하고역순으로리스트를정렬한 후에가장많은커밋을한사람을출력하세요.
145 11. 연습문제 127 Sample Line: From Sat Jan 5 09:14: Enter a file name: mbox-short.txt cwen@iupui.edu 5 Enter a file name: mbox.txt zqian@umich.edu 195 Exercise 10.2 이번프로그램은각메시지에대한하루중시간의분포를계수 (count)한다. From 라인으로부터 시간 문자열을 찾고 콜론(:) 문자를 사용하 여문자열을쪼개서시간을추출합니다.각시간별로계수(count)를누적하고 아래에보여지듯이시간단위로정렬하여한라인에한시간씩계수(count)를출 력합니다. Sample Execution: python timeofday.py Enter a file name: mbox-short.txt Exercise 10.3 파일을 읽고, 빈도(frequencey)에 따라 내림차순으로 문자(letters) 를출력하는프로그램을 작성하세요. 작성한프로그램은모든 입력을소문자로 변환하고 a-z문자만계수(count)한다.공백,숫자,문장기호 a-z를제외한다른 어떤것도계수하지않습니다.다른언어로구성된텍스트샘플을구해서언어 마다 문자 빈도가 어떻게 변하는지 살펴보세요. 결과를 wikipedia.org/wiki/ Letter_frequencies 표와 비교하세요.
146 128 제 10 장. 튜플(Tuples)
147 제 11 장 정규표현식 지금까지파일을훑어서패턴을찾고,관심있는라인에서다양한비트(bits)를 뽑아냈다. split, find 같은문자열메쏘드를사용하였고,라인에서 일정부분 을 뽑아내기 위해서 리스트와 문자열 슬라이싱(slicing)을 사용했다. 검색하고추출하는 작업은너무 자주 있는 일이어서파이썬은상기와 같은 작업 을 매우 우아하게 처리하는 정규 표현식(regular expressions)으로 불리는 매우 강력한라이브러리를제공한다.정규표현식을책의앞부분에소개하지않은 이유는정규표현식라이브러리가매우 강력하지만,약간복잡하고,구문에 익 숙해지는데 시간이 필요하기 때문이다. 정규표현식은문자열을 검색하고파싱하는데그자체가 작은프로그래밍언어 다.사실,책전체가정규표현식을주제로쓰여진책이몇권 있다. 이번 장에서는 정규표현식의기초만을다룰 것이다.정규표현식의좀더 자세한사항은다음을 참조하라. 정규 표현식 라이브러리는 사용하기 전에 프로그램을 가져오기(import)해야 한 다.정규표현식라이브러리의 가장 간단한쓰임은search() 검색함수다.다음 프로그램은 검색 함수의 사소한 사용례를 보여준다. import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() if re.search('from:', line) : print line 파일을열고, 각라인을루프로반복해서정규표현식 search()메쏘드를호 출하여문자열 From 이포함된라인만출력한다.상기프로그램은진정으로 강력한정규표현식기능을사용하지않았다.왜냐하면,line.find()메쏘드를 가지고동일한 결과를쉽게구현할수있기때문이다.
148 130 제 11 장. 정규 표현식 정규표현식의 강력한기능은문자열에해당하는라인을좀더정확하게제어 하기 위해서 검색문자열에특수문자를추가할때확인될수있다.매우적은 코드를 작성할지라도,정규표현식에특수문자를추가하는 것만으로도정교한 일치(matching)와추출이 가능하게한다. 예를들어,탈자기호(caret)는라인의 시작 과 일치하는정규표현식에사용 된다. 다음과 같이 From: 으로 시작하는 라인만 일치하도록 응용프로그램을 변경할수있다. import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() if re.search('^from:', line) : print line From: 문자열로시작하는라인만 일치할수있다.여전히매우 간단한프로 그램으로 문자열 라이브러리에서 startswith() 메쏘드로 동일하게 수행할 수 있다.하지만,무엇을정규표현식과매칭하는가에대해특수액션문자를담아 좀더많은제어를할수 있게하는정규표현식 개념을소개하기에는충분하다. 제 1절 정규표현식의문자매칭 좀더 강력한정규표현식을 작성할수있는다른특수문자는많이 있다. 가장 자주사용되는특수문자는 임의문자를매칭하는마침표다. 다음예제에서정규표현식 F..m: 은 From:, Fxxm:, F12m:, F!@m: 같은 임의문자열을매칭한다.왜냐하면정규표현식마침표문자가 임의의문 자와 매칭되기 때문이다. import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() if re.search('^f..m:', line) : print line 정규표현식에 *, + 문자를사용하여문자가원하는만큼반복을나타내는 기능과 결합되었을때는더욱 강력해진다. *, + 특수문자가 검색문자열 에문자하나만을매칭하는대신에별표기호인 경우 0혹은그이상의매칭, 더하기기호인 경우 1혹은그이상의문자의매칭을 의미한다. 다음예제에서반복와일드 카드(wild card)문자를사용하여매칭하는라인을 좀더좁힐수있다. import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() if re.search('^from:.+@', line) : print line
149 2. 정규표현식사용데이터추출 131 검색문자열 은 From: 으로시작하고,.+ 하나혹은그이상 라인은매칭이될것이다. From: 것으로.+ 와이 드 카드를 간주할수있다. 더하기와별표기호를 밀어내기(pushy) 문자로생각하는 것이좋다.예를들 어,다음문자열은.+ 특수문자가다음에보여주듯이밖으로밀어내는 것처럼 문자열마지막@기호를매칭한다. From: stephen.marquard@uct.ac.za, csev@umich.edu, and 다른 특수문자를 추가함으로서 별표나 더하기 기호가 너무 탐욕(greedy) 스 럽지않게만들수있다.와일드 카드특수문자의탐욕스러운기능을끄는 것에 대해서는 자세한 정보를 참조바란다. 제 2절 정규표현식사용데이터추출 파이썬으로 문자열에서 데이터를 추출하려면, findall() 메쏘드를 사용해서 정규표현식과매칭되는모든부속문자열을추출할수있다.형식에관계없이 임의라인에서전자우편주소 같은문자열을추출하는예제를사용하자.예를 들어,다음 각라인에서전자우편주소를뽑아내고자한다. From stephen.marquard@uct.ac.za Sat Jan 5 09:14: Return-Path: <postmaster@collab.sakaiproject.org> for <source@collab.sakaiproject.org>; Received: (from apache@localhost) Author: stephen.marquard@uct.ac.za 각각의라인에대해서다르게쪼개고,슬라이싱하면서라인 각각의형식에맞 추어코드를 작성하고는싶지는않다.다음프로그램은 findall()메쏘드를 사용하여전자우편주소가 있는라인을찾아내고하나혹은그이상의주소를 뽑아낸다. import re s = 'Hello from csev@umich.edu to cwen@iupui.edu about the lst = re.findall('\s+@\s+', s) print lst findall()메쏘드는두번째 인자문자열을찾아서전자우편주소처럼보이는 모든문자열을리스트로반환한다. 공백이아닌문자 (\S)와매칭되는두문자 순서(sequence)를 사용한다. 프로그램의출력은다음과 같다. ['csev@umich.edu', 'cwen@iupui.edu']
150 132 제 11 장. 정규 표현식 정규표현식을해석하면,적어도하나의 이 상의 공백이아닌문자를 가진부속문자열을찾는다.또한, \S+ 특수문자는 가능한많이 공백이아닌문자를매칭한다. (정규표현식에서 탐욕(greedy) 매칭이라고부른다.) 정규 표현식은 두번 공백이아닌문자가하 나도없기때문이다.프로그램의정규표현식을사용해서파일에모든라인을 읽고다음과 같이전자우편주소처럼보이는모든문자열을출력한다. import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() x = re.findall('\s+@\s+', line) if len(x) > 0 : print x 각라인을 읽어들이고,정규표현식과매칭되는모든부속문자열을추출한다. findall()메쏘드는리스트를반환하기때문에,전자우편처럼보이는부속문 자열을적어도하나찾아서출력하기 위해서반환리스트요소숫자가 0보다 큰지여부를 간단히확인한다. mbox.txt파일에프로그램을실행하면,다음출력을얻는다. ['wagnermr@iupui.edu'] ['cwen@iupui.edu'] ['<postmaster@collab.sakaiproject.org>'] ['< m03LMFo @nakamura.uits.iupui.edu>'] ['<source@collab.sakaiproject.org>;'] ['<source@collab.sakaiproject.org>;'] ['<source@collab.sakaiproject.org>;'] ['apache@localhost)'] ['source@collab.sakaiproject.org;'] 전자우편주소몇몇은 <, ; 같은 잘못된문자가앞과뒤에붙어있다.문자나 숫자로 시작하고 끝나는 문자열 부분만 관심있다고 하자. 그러기 위해서,정규표현식의또다른기능을사용한다.매칭하려는다중허 용문자집합을표기하기 위해서꺾쇠괄호를사용한다.그런 의미에서 \S 은 공백이아닌문자집합을매칭하게한다. 이제매칭하려는문자에관해서좀더 명확해졌다. 여기새로운정규표현식이 있다. [a-za-z0-9]\s*@\s*[a-za-z] 약간복잡해졌다.왜정규표현식이 자신만의언어인가에대해서 이해할수있 다. 이정규표현식을해석하면, 0혹은그이상의 공백이아닌문자( \S* )로 하나의소문자,대문자혹은숫자( [a-za-z0-9] )를 0혹은그 이상의 공백이아닌문자( \S* )로하나의소문자,대문자혹은숫자( [a-za- Z0-9] )로된부속문자열을찾는다. 0혹은그이상의 공백이아닌문자를나 타내기 위해서 + 에서 * 으로 바꿨다. 왜냐하면 [a-za-z0-9] 자체가 이미
151 3. 검색과추출조합하기 133 하나의 공백이아닌문자이기때문이다. *, + 는단일문자에별표,더하기 기호 왼편에 즉시 적용됨을 기억하세요. 프로그램에정규표현식을사용하면,데이터가훨씬깔끔해진다. import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() x = re.findall('[a-za-z0-9]\s*@\s*[a-za-z]', line) if len(x) > 0 : print x... ['wagnermr@iupui.edu'] ['cwen@iupui.edu'] ['postmaster@collab.sakaiproject.org'] [' m03LMFo @nakamura.uits.iupui.edu'] ['source@collab.sakaiproject.org'] ['source@collab.sakaiproject.org'] ['source@collab.sakaiproject.org'] ['apache@localhost'] source@collab.sakaiproject.org 라인에서 문자열 끝에 >; 문자를 정규 표 현식으로 제거한 것을 주목하세요. 정규 표현식 끝에 [a-za-z] 을 추가하여서 정규표현식파서가찾는 임의문자열은문자로만끝나야되기때문이다.그래 서, sakaiproject.org>; 에서 > 을 봤을 때, g 가 마지막 맞는 매칭이 되고, 거기서마지막매칭을마치고중단한다. 프로그램의출력은리스트의단일요소를 가진문자열로파이썬리스트이다. 제 3절 검색과추출조합하기 다음과 같은 X- 문자열로시작하는라인의숫자를찾고자한다면, X-DSPAM-Confidence: X-DSPAM-Probability: 임의의라인에서 임의부동소수점숫자가아니라상기구문을 가진라인에서만 숫자를추출하고자한다. 라인을선택하기 위해서다음과 같이정규표현식을구성한다. ^X-.*: [0-9.]+ 정규표현식을해석하면,''^''에서 X- 으로시작하고,.* 에서 0혹은그이 상의문자를 가지며,콜론( : )이나오고나서 공백을만족하는라인을찾는다. 공백뒤에 [0-9.]+ 에서숫자 (0-9)혹은점을 가진하나혹은그이상의문자 가 있여야한다.꺽쇠기호사이에마침표는실제마침표만매칭함을주목하기 바란다. (즉, 꺾쇠 기호 사이는 와일드 카드 문자가 아니다.) 관심을 가지고 있는특정한라인과매우정확하게매칭이되는매우빠듯한정규 표현식으로다음과 같다.
152 134 제 11 장. 정규 표현식 import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() if re.search('^x\s*: [0-9.]+', line) : print line 프로그램을 실행하면, 잘 걸러져서 찾고자 하는 라인만 볼 수 있다. X-DSPAM-Confidence: X-DSPAM-Probability: X-DSPAM-Confidence: X-DSPAM-Probability: 하지만, 이제 rsplit 사용해서 숫자를 뽑아내는 문제를 해결해야 한다. rsplit 을사용하는 것이 간단해보이지만,동시에라인을 검색하고파싱하기 위해서 정규표현식의또다른기능을사용할수있다. 괄호는정규표현식의또다른특수문자다.정규표현식에괄호를추가한다면, 문자열이매칭될때,무시된다.하지만, findall()을사용할때,매칭할전체 정규표현식을원할지라도,정규표현식을매칭하는부속문자열의부분만을 뽑아낸다는 것을괄호가표시한다. 그래서,프로그램을다음과 같이수정한다. import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() x = re.findall('^x\s*: ([0-9.]+)', line) if len(x) > 0 : print x search()을호출하는대신에,매칭문자열의부동소수점숫자만뽑아내는 findall()에원하는부동소수점숫자를표현하는정규표현식부분에괄호를 추가한다. 프로그램의출력은다음과 같다. ['0.8475'] ['0.0000'] ['0.6178'] ['0.0000'] ['0.6961'] ['0.0000'].. 숫자가여전히리스트에 있어서문자열에서부동소수점으로변환할필요가 있지만,흥미로운정보를찾아뽑아내기 위해서정규표현식의 강력한힘을사 용했다. 이기술을활용한또다른예제로,파일을살펴보면,폼(form)을 가진라인이 많다.
153 3. 검색과추출조합하기 135 Details: 상기언급한동일한기법을사용하여모든변경번호(라인의끝에정수숫자)를 추출하고자한다만,다음과 같이프로그램을 작성할수있다. import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() x = re.findall('^details:.*rev=([0-9.]+)', line) if len(x) > 0: print x 작성한정규표현식을해석하면, Details: 로시작하는.* 에 임의의문자들 로, rev= 을포함하고나서,하나혹은그이상의숫자를 가진라인을찾는다. 전체정규표현식을만족하는라인을찾고자하지만,라인끝에정수만을추출 하기 위해서 [0-9]+ 을 괄호로 감쌌다. 프로그램을실행하면,다음출력을얻는다. ['39772'] ['39771'] ['39770'] ['39769']... [0-9]+ 은 탐욕(greedy) 스러워서, 숫자를 추출하기 전에 가능한 큰 문자열 숫자를 만들려고 한다는 것을 기억하라. 이런 탐욕(greedy) 스러운 행동으로 인해서왜각숫자로모두 5자리숫자를얻은 이유가된다.정규표현식라이브 러리는양방향으로파일처음이나끝에숫자가아닌 것을마주칠때까지뻗어 나간다. 이제정규표현식을사용해서 각전자우편메시지의요일에관심이 있었던책 앞의연습프로그램을다시 작성한다.다음형식의라인을찾는다. From stephen.marquard@uct.ac.za Sat Jan 5 09:14: 그리고나서, 각라인의요일의시간을추출하고자한다.앞에서 split를두번 호출하여 작업을수행했다.첫번째는라인을단어로쪼개고,다섯번째단어를 뽑아내서,관심있는두문자를뽑아내기 위해서콜론문자에서다시쪼갰다. 작동을할지모르지만,실질적으로정말부서지기쉬운코드로라인이 잘짜여져 있다고 가정하에 가능하다. 잘못된형식의라인이나타날때도 결코망가지지 않는프로그램을담보하기 위해서충분한오류 검사기능을추가하거나 커다란 try/except블록을넣으면,참읽기힘든 10-15라인코드로 커질 것이다. 다음정규표현식으로훨씬 간결하게 작성할수있다. ^From.* [0-9][0-9]: 상기정규표현식을해석하면, 공백을포함한 From 으로시작해서,.* 에 임의 갯수의문자,그리고 공백,두개의숫자 [0-9][0-9] 뒤에콜론(:)문자를 가진라인을찾는다. 일종의찾고 있는라인에대한정의다.
154 136 제 11 장. 정규 표현식 findall()을사용해서단지시간만뽑아내기 위해서,두숫자에괄호를다음과 같이추가한다. ^From.* ([0-9][0-9]): 작업 결과는 다음과 같이 프로그램에 반영한다. import re hand = open('mbox-short.txt') for line in hand: line = line.rstrip() x = re.findall('^from.* ([0-9][0-9]):', line) if len(x) > 0 : print x 프로그램을실행하면,다음출력 결과가나온다. ['09'] ['18'] ['16'] ['15']... 제 4절 이스케이프(Escape)문자 라인의처음과끝을매칭하거나,와일드 카드를명세하기 위해서정규표현식 의특수문자를사용했기때문에,정규표현식에사용된문자가 정상(normal) 적인문자임을표기할방법이필요하고달러기호와탈자기호(^) 같은실제문 자를매칭하고자한다. 역슬래쉬( )를 가진문자를앞에덮붙여서문자를단순히매칭하고자한다고나 타낼수있다.예를들어,다음정규표현식으로금액을찾을수있다. import re x = 'We just received $10.00 for cookies.' y = re.findall('\$[0-9.]+',x) 역슬래쉬달러기호를앞에덮붙여서,실제로 라인끝(end of line) 매칭대신 에 입력문자열의달러기호와매칭한다.정규표현식나머지부분은하나혹은 그 이상의숫자혹은소수점문자를매칭한다.주목:꺾쇠괄호내부에문자는 특수문자 가아니다.그래서 [0-9.] 은실제숫자혹은점을 의미한다.꺾쇠 괄호외부에점은 와일드 카드(wild-card) 문자이고 임의의문자와매칭한다. 꺾쇠 괄호 내부에서 점은 점일 뿐이다. 제 5절 요약 지금까지정규표현식의표면을긁은정도지만,정규표현식언어에대해서조금 학습했다. 정규 표현식은 특수 문자로 구성된 검색 문자열로 매칭(matching)
155 5. 요약 137 정의하고매칭된문자열로부터추출된 결과물을정규표현식시스템과프로그 래머가 의도한바를 의사소통하는 것이다.다음에특수문자및문자시퀀스의 일부가 있다. ^ 라인의처음을매칭. $ 라인의끝을매칭.. 임의의 문자를 매칭(와일드 카드) \s 공백문자를매칭. \S 공백이아닌문자를매칭.(\s 의반대). * 바로앞선문자에적용되고 0혹은그이상의앞선문자와매칭을표기함. *? 바로앞선문자에적용되고 0혹은그이상의앞선문자와매칭을 탐욕적이지 않은(non-greedy)방식 으로표기함. + 바로앞선문자에적용되고 1혹은그이상의앞선문자와매칭을표기함. +? 바로앞선문자에적용되고 1혹은그이상의앞선문자와매칭을 탐욕적이지 않은(non-greedy)방식 으로표기함. [aeiou] 명세된집합문자에존재하는단일문자와매칭.다른문자는안되고, a, e, i, o, u 문자만매칭되는예제. [a-z0-9] 음수기호로문자범위를명세할수있다.소문자이거나숫자인단일문자만 매칭되는 예제. [^A-Za-z] 집합표기의첫문자가 ^인 경우,로직을 거꾸로적용한다.대문자나혹은소문 자가아닌 임의단일문자만매칭하는예제. ( ) 괄호가정규표현식에추가될때,매칭을무시한다.하지만 findall()을사용 할때전체문자열보다매칭된문자열의상세한부속문자열을추출할수있게 한다. \b 빈문자열을매칭하지만,단어의시작과끝에만사용된다.
156 138 제 11 장. 정규 표현식 \B 빈문자열을매칭하지만,단어의시작과끝이아닌 곳에사용된다. \d 임의 숫자와 매칭하여 [0-9] 집합에 상응함. \D 임의 숫자가 아닌 문자와 매칭하여 [^0-9] 집합에 상응함. 제 6절 유닉스사용자를 위한보너스 정규표현식을사용하여파일을 검색기능은 1960년대 이래로 유닉스운영시스 템에내장되어여러가지형태로 거의모든프로그래밍언어에서 이용가능하다. 사실, search() 예제에서와 거의 동일한 기능을 하는 grep (Generalized Regular Expression Parser)으로 불리는 유닉스 내장 명령어 프로그램이 있다. 그래 서,맥킨토시나리눅스운영시스템을 가지고 있다면,명령어창에서다음명령 어를시도할수있다. $ grep '^From:' mbox-short.txt From: stephen.marquard@uct.ac.za From: louis@media.berkeley.edu From: zqian@umich.edu From: rjlowe@iupui.edu grep을 사용하여, mbox-short.txt 파일 내부에 From: 문자열로 시작하는 라인을보여준다. grep명령어를 가지고약간실험을하고 grep에대한문서를 읽는다면,파이썬에서지원하는정규표현식과grep에서지원되는정규표현식 과차이를발견할 것이다.예를들어, grep 공백이아닌문자 \S 을지원하지 않는다.그래서약간더복잡한집합표기 [^ ] 을사용해야한다. [^ ] 은 간단 히정리하면, 공복을제외한 임의의문자와매칭한다. 제 7절 디버깅 만약특정메쏘드의정확한 이름을기억해내기 위해서빠르게생각나게하는 것 이필요하다면도움이많이될수있는 간단하고초보적인내장문서가파이썬에 포함되어 있다.내장문서도움말은 인터랙티브모드의파이썬 인터프리터에서 볼수있다. help()를 사용하여 인터랙티브 도움을 받을 수 있다. >>> help() Welcome to Python 2.6! This is the online help utility. If this is your first time using Python, you should definitely check out the tutorial on the Internet at
157 8. 용어정의 139 Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and return to the interpreter, just type "quit". To get a list of available modules, keywords, or topics, type "modules", "keywords", or "topics". Each module also comes with a one-line summary of what it does; to list the modules whose summaries contain a given word such as "spam", type "modules spam". help> modules 특정한모듈을사용하고자한다면,dir()명령어를사용하여다음과 같이모듈 의메쏘드를찾을수있다. >>> import re >>> dir(re) [.. 'compile', 'copy_reg', 'error', 'escape', 'findall', 'finditer', 'match', 'purge', 'search', 'split', 'sre_compile', 'sre_parse', 'sub', 'subn', 'sys', 'template'] 또한, dir()명령어를사용하여특정메쏘드에대한짧은문서도움말을얻을 수 있다. >>> help (re.search) Help on function search in module re: search(pattern, string, flags=0) Scan through string looking for a match to the pattern, returning a match object, or None if no match was found. >>> 내장문서는광범위하지않아서,급하거나,웹브라우저나 검색엔진에접근할 수없을때도움이될수있다. 제 8절 용어정의 부서지기 쉬운 코드(brittle code): 입력 데이터가 특정한 형식일 경우에만 작 동하는코드.하지만올바른형식에서약간이도벗아나게되면깨지기쉽 니다.쉽게부서지기때문에 부서지기쉬운코드(brittle code) 라고부 른다. 욕심쟁이 매칭(greedy matching): 정규 표현식의 +, * 문자는 가능한 큰 문자열을 매칭하기 위해서 밖으로 확장하는 개념. grep: 정규표현식에매칭되는파일을탐색하여라인을찾는데대부분의 유 닉스 시스템에서 사용가능한 명령어. "Generalized Regular Expression Parser"의약자. 정규 표현식(regular expression): 좀더 복잡한 검색 문자열을 표현하는 언어. 정규표현식은특수문자를포함해서 검색라인의처음혹은끝만매칭하 거나많은비슷한 것을매칭한다.
158 140 제 11 장. 정규 표현식 와일드 카드(wild card): 임의문자를매칭하는특수문자.정규표현식에서와 이드 카드문자는마침표문자다. 제 9절 연습문제 Exercise 11.1 유닉스의 grep명령어를모사하는간단한프로그램을 작성하세 요.사용자가정규표현식을 입력하고정규표현식에매칭되는라인수를셈하는 프로그램입니다. $ python grep.py Enter a regular expression: ^Author mbox.txt had 1798 lines that matched ^Author $ python grep.py Enter a regular expression: ^Xmbox.txt had lines that matched ^X- $ python grep.py Enter a regular expression: java$ mbox.txt had 4218 lines that matched java$ Exercise 11.2 다음형식의라인만을찾는프로그램을 작성하세요. New Revision: 그리고,정규표현식과 findall()메쏘드를사용하여각라인으로부터숫자를 추출하세요.숫자들의평균을구하고출력하세요. Enter file:mbox.txt Enter file:mbox-short.txt
159 제 12 장 네트워크 프로그램 지금까지책의많은예제는파일을 읽고파일의정보를찾는데집중했지만,다 양한많은정보의원천이 인터넷에 있다. 이번 장에서는 웹브라우져로 가장하고 HTTP 프로토콜(HyperText Transport Protocol,HTTP)을 사용하여 웹페이지를 검색할 것이다. 웹페이지 데이터를 읽 고파싱할 것이다. 제 1 절 하이퍼 텍스트 전송 프로토콜(HyperText Transport Protocol - HTTP) 웹에 동력을 공급하는 네트워크 프로토콜은 실제로 매우 단순하다. 파이썬에는 소켓 (sockets)이라고불리는내장지원모듈이 있다.파이썬프로그램에서 소켓모듈을통해서네트워크연결을하고,데이터 검색을매우용이하게한다. 소켓(socket)은단일소켓으로두프로그램사이에양방향연결을제공한다는 점을 제외하고 파일과 매우 유사하다. 동일한 소켓에 읽거나 쓸 수 있다. 소켓에 무언가를쓰게되면,소켓의다른끝에 있는 응용프로그램에전송된다.소켓으 로부터 읽게 되면, 다른 응용 프로그램이 전송한 데이터를 받게 된다. 하지만,소켓의다른쪽끝에프로그램이어떠한데이터도전송하지않았는데 소켓을 읽으려고하면,단지앉아서기다리기만한다.만약어떠한 것도보내지 않고양쪽소켓끝의프로그램모두기다리기만한다면,모두매우오랜시간동 안기다리게될것이다. 인터넷으로통신하는프로그램의중요한부분은특정종류의프로토콜을 공유 하는 것이다.프로토콜(protocol)은정교한규칙의집합으로누가메시지를먼저 보내고,메세지로무엇을하며,메시지에대한 응답은무엇이고,다음에누가메 세지를보내고등등을포함한다. 이런관점에서소켓끝의두응용프로그램이 함께춤을추고 있으니,다른사람발을밟지않도록확인해야한다. 네트워크프로토콜을기술하는문서가많이 있다.하이퍼텍스트전송프로토콜 (HyperText Transport Protocol)은다음문서에기술되어 있다.
160 142 제 12 장. 네트워크 프로그램 매우상세한 176페이지나되는 장문의복잡한문서다.흥미롭다면시간을 가 지고 읽어보기 바란다. RFC2616에 36 페이지를 읽어보면, GET 요청(request) 에 대한 구문을 발견하게 된다. 꼼꼼히 읽게 되면, 웹서버에 문서를 요청하기 하 기 위해서, 80포트로 라인을전송한다. GET HTTP/1.0 두번째매개변수는요청하는웹페이지가된다.그리고또한빈라인도전송한 다.웹서버는문서에대한헤더정보와빈라인그리고문서본문으로 응답한다. 제 2 절 세상에서 가장 간단한 웹 브라우져(Web Browser) 아마도 HTTP프로토콜이어떻게 작동하는지알아보는 가장 간단한방법은매 우 간단한파이썬프로그램을 작성하는 것이다.웹서버에접속하고 HTTP프 로토콜규칙에따라문서를요청하고서버가다시보내주는 결과를보여주는 것이다. import socket mysock = socket.socket(socket.af_inet, socket.sock_stream) mysock.connect((' 80)) mysock.send('get HTTP/1.0\n\n') while True: data = mysock.recv(512) if ( len(data) < 1 ) : break print data mysock.close() 처음에프로그램은 80포트로연결한다. 웹브라우 져 역할로 작성된프로그램이하기때문에 HTTP프로토콜은 GET명령어를 공백 라인과 함께 보낸다. 사용자로컬컴퓨터 웹 서버 web server) 송신 send) 수신 recv) 소켓 socket) 80 웹페이지..... 공백라인을보내자마자, 512문자덩어리의데이터를소켓에서받아더이상 읽을데이터가없을때까지(즉, recv()이빈문자열을반환한다.)데이터를출력 하는루프를 작성한다.
161 3. HTTP를 통해서 이미지 가져오기 143 프로그램실행결과다음을얻을수있다. HTTP/ OK Date: Sun, 14 Mar :52:41 GMT Server: Apache Last-Modified: Tue, 29 Dec :31:22 GMT ETag: "143c1b33-a7-4b395bea" Accept-Ranges: bytes Content-Length: 167 Connection: close Content-Type: text/plain But soft what light through yonder window breaks It is the east and Juliet is the sun Arise fair sun and kill the envious moon Who is already sick and pale with grief 출력결과는 웹서버가 문서를 기술하기 위해서 보내는 헤더(header)로 시작한 다. 예를 들어, Content-Type 헤더는 문서가 일반 텍스트 문서(text/plain) 임을표기한다. 서버가헤더를보낸후에,빈라인을추가해서헤더끝임을표기하고나서실제 파일romeo.txt을보낸다. 이예제를통해서소켓을통해서저수준(low-level)네트워크연결을어떻게하 는지확인할수있다.소켓을사용해서웹서버,메일서버혹은다른종류의서버 와통신할수있다.필요한 것은프로토콜을기술하는문서를찾고프로토콜에 따라데이터를주고받는코드를 작성하는 것이다. 하지만, 가장흔히사용하는프로토콜은 HTTP (즉,웹)프로토콜이기때문에, 파이썬에는 HTTP프로토컬을지원하기 위해특별히설계된라이브러리가 있 다. 이것을통해서웹상에서데이터나문서를 검색을쉽게할수있다. 제 3절 HTTP를통해서 이미지 가져오기 상기예제에서는파일에새줄(newline)이 있는 일반텍스트파일을 가져왔다. 그리고나서,프로그램을실행해서데이터를단순히화면에복사했다. HTTP를 사용하여 이미지를 가져오도록비슷하게프로그램을 작성할수있다.프로그 램실행시에화면에데이터를복사하는대신에,데이터를문자열로누적하고, 다음과 같이 헤더를 잘라내고 나서 파일에 이미지 데이터를 저장한다. import socket import time mysock = socket.socket(socket.af_inet, socket.sock_stream) mysock.connect((' 80)) mysock.send('get HTTP/1.0\n\n') count = 0 picture = "";
162 144 제 12 장. 네트워크 프로그램 while True: data = mysock.recv(5120) if ( len(data) < 1 ) : break # time.sleep(0.25) count = count + len(data) print len(data),count picture = picture + data mysock.close() # Look for the end of the header (2 CRLF) pos = picture.find("\r\n\r\n"); print 'Header length',pos print picture[:pos] # Skip past the header and save the picture data picture = picture[pos+4:] fhand = open("stuff.jpg","wb") fhand.write(picture); fhand.close() 프로그램을실행하면,다음과 같은출력을생성한다. $ python urljpeg.py Header length 240 HTTP/ OK Date: Sat, 02 Nov :15:07 GMT Server: Apache Last-Modified: Sat, 02 Nov :01:26 GMT ETag: "19c a9-4ea280f8354b8" Accept-Ranges: bytes Content-Length: Connection: close Content-Type: image/jpeg 상기 url에 대해서, Content-Type 헤더가 문서 본문이 이미지(image/jpeg) 를나타내는 것을볼수있다.프로그램이완료되면, 이미지뷰어로 stuff.jpg 파일을열어서 이미지데이터를볼수있다. 프로그램을실행하면, recv()메쏘드를호출할때마다 5120문자는전달받지 못하는 것을볼수있다. recv()호출하는순간마다웹서버에서네트워크로전 송되는 가능한많은문자를받을뿐이다.매번 5120문자까지요청하지만, 1460 혹은 2920문자만전송받는다.
163 4. urllib 사용하여 웹페이지 가져오기 145 결과값은네트워크속도에따라달라질수있다. recv()메쏘드마지막호출에 는스트림마지막인 1681바이트만받았고, recv()다음호출에는 0길이문자 열을전송받아서,서버가소켓마지막에 close()메쏘드를호출하고더이상의 데이터가 없다는 신호를 준다. 주석 처리한 time.sleep()을 풀어줌으로써 recv() 연속 호출을 늦출 수 있다. 이런 방식으로 매번 호출 후에 0.25초 기다리게 한다. 그래서, 사용자가 recv() 메쏘드를호출하기전에서버가먼저도착할수있어서더많은데이터를보낼 수가 있다.정지시간을넣어서프로그램을다시실행하면다음과 같다. $ python urljpeg.py Header length 240 HTTP/ OK Date: Sat, 02 Nov :22:04 GMT Server: Apache Last-Modified: Sat, 02 Nov :01:26 GMT ETag: "19c a9-4ea280f8354b8" Accept-Ranges: bytes Content-Length: Connection: close Content-Type: image/jpeg recv()메쏘드호출의처음과마지막을제외하고,매번새로운데이터를요청 할 때마다 이제 5120 문자가 전송된다. 서버 send()요청과 응용프로그램 recv()요청사이에버퍼가 있다.프로그 램에지연을넣어실행하게될때,어느지점엔가서버가소켓버퍼를채우고 응용프로그램이 버퍼를 비울 때까지 잠시 멈춰야 된다. 송신하는 응용프로그램 혹은수신하는 응용프로그램을멈추게하는행위를 흐름제어(flow control) 이라고한다. 제 4절 urllib사용하여웹페이지 가져오기 수작업으로소켓라이브러리를사용하여 HTTP로데이터를주고받을수있지 만, urllib라이브러리를사용하여파이썬에서동일한 작업을수행하는좀더 간편한방식이 있다. urllib을사용하여파일처럼웹페이지를다룰수가 있다.단순하게어느웹페이 지를 가져올 것인지만지정하면 urllib라이브러리가모든 HTTP프로토콜과 헤더관련 사항을 처리해 준다. 웹에서 romeo.txt 파일을 읽도록 urllib를 사용하여 작성한 상응 코드는 다음 과 같다.
164 146 제 12 장. 네트워크 프로그램 import urllib fhand = urllib.urlopen(' for line in fhand: print line.strip() urllib.urlopen을사용하여웹페이지를열게되면,파일처럼다룰수있고for 루프를사용하여데이터를 읽을수있다. 프로그램을실행하면,파일내용출력결과만을볼수있다.헤더정보는여전히 전송되었지만, urllib 코드가 헤더를 받아 내부적으로 처리하고, 사용자에게는 단지 데이터만 반환한다. But soft what light through yonder window breaks It is the east and Juliet is the sun Arise fair sun and kill the envious moon Who is already sick and pale with grief 예제로,romeo.txt데이터를 가져와서파일의 각단어빈도를 계산하는프로그 램을다음과 같이 작성할수있다. import urllib counts = dict() fhand = urllib.urlopen(' for line in fhand: words = line.split() for word in words: counts[word] = counts.get(word,0) + 1 print counts 다시한번,웹페이지를열게되면,로컬파일처럼웹페이지를 읽을수있다. 제 5절 HTML파싱과웹스크래핑 파이썬 urllib 활용하는 일반적인 사례는 웹 스크래핑(scraping)이다. 웹 스크 래핑은웹브라우저를 가장한프로그램을 작성하는 것이다.웹페이지를 가져와 서,패턴을찾아페이지내부의데이터를꼼꼼히조사한다.예로,구글같은 검 색엔진은웹페이지의소스를조사해서다른페이지로 가는링크를추출하고, 그해당페이지를 가져와서링크추출하는 작업을반복한다. 이러한기법으로 구글은웹상의 거의모든페이지를 거미(spiders)줄처럼연결한다. 구글은또한발견한웹페이지에서특정페이지로연결되는링크빈도를사용 하여얼마나중요한페이지인지를 측정하고 검색결과에페이지가얼마나높은 순위로 노출되어야 하는지 평가한다. 제 6절 정규표현식사용 HTML파싱하기 HTML을파싱하는 간단한방식은정규표현식을사용하여특정한패턴과매칭 되는부속문자열을반복적으로찾아추출하는 것이다.
165 6. 정규 표현식 사용 HTML 파싱하기 147 여기 간단한 웹페이지가 있다. <h1>the First Page</h1> <p> If you like, you can switch to the <a href=" Second Page</a>. </p> 모양 좋은 정규표현식을 구성해서 다음과 같이 상기 웹페이지에서 링크를 매칭 하고추출할수있다. href=" 작성된 정규 표현식은 href=" 로 시작하고, 하나 이상의 문자를.+? 가지고 큰 따옴표를 가진 문자열을 찾는다..+? 에 물음표가 갖는 의미는 매칭 이 욕심쟁이(greedy) 방식보다 비욕심쟁이(non-greedy) 방식으로 수행됨 을 나타낸다. 비욕심쟁이(non-greedy) 매칭방식은 가능한 가장 적게 매칭되는 문자열을찾는방식이고,욕심방식은 가능한 가장크게매칭되는문자열을찾 는방식이다. 추출하고자하는문자열이매칭된문자열의어느부분인지를표기하기 위해서 정규 표현식에 괄호를 추가하여 다음과 같이 프로그램을 작성한다. import urllib import re url = raw_input('enter - ') html = urllib.urlopen(url).read() links = re.findall('href="( html) for link in links: print link findall정규표현식메쏘드는정규표현식과매칭되는모든문자열리스트를 추출하여큰따옴표사이에링크텍스트만을반환한다. 프로그램을실행하면,다음출력을얻게된다. python urlregex.py Enter python urlregex.py Enter 정규표현식은 HTML이예측가능하고 잘구성된 경우에멋지게 작동한다.하 지만, 망가진 HTML페이지가많아서,정규표현식만을사용하는솔류션은 유효한링크를놓치거나 잘못된데이터만찾고끝날수있다. 이문제는 강건한 HTML파싱라이브러리를사용해서해결될수있다.
166 148 제 12 장. 네트워크 프로그램 제 7절 BeautifulSoup사용한 HTML파싱 HTML을파싱하여페이지에서데이터를추출할수있는파이썬라이브러리는 많이 있다.라이브러리 각각은 강점과약점이 있어서사용자필요에따라취사 선택한다. 예로, 간단하게 HTML 입력을 파싱하여 BeautifulSoup 라이브러리를 사용하 여링크를추출할 것이다.다음웹사이트에서 BeautifulSoup코드를다운로드 받아설치할수있다. BeautifulSoup 라이브러리를 다운로드 받아 설치 하거나 BeautifulSoup.py 파일을 응용프로그램과동일한폴더에저장한다. HTML이 XML처럼보이고몇몇페이지는 XML로되도록꼼꼼하게구축되었 지만, 일반적으로대부분의 HTML이깨져서 XML파서가 HTML전체페이지 를 잘못구성된 것으로 간주하고받아들이지않는다. BeautifulSoup라이브러 리는 결점많은 HTML페이지에내성이 있어서사용자가필요로하는데이터를 쉽게추출할수있게한다. urllib를 사용하여 페이지를 읽어들이고, BeautifulSoup를 사용해서 앵커 태 그 (a)로부터 href 속성을 추출한다. import urllib from BeautifulSoup import * url = raw_input('enter - ') html = urllib.urlopen(url).read() soup = BeautifulSoup(html) # Retrieve all of the anchor tags tags = soup('a') for tag in tags: print tag.get('href', None) 프로그램이웹주소를 입력받고,웹페이지를열고,데이터를 읽어서 Beautiful- Soup파서에전달하고,그리고나서모든앵커태그를불러와서 각태그별로 href속성을출력한다. 프로그램을실행하면,아래와 같다. python urllinks.py Enter python urllinks.py Enter
167 8. urllib을사용하여바이너리파일 읽기 149 BeautifulSoup을사용하여다음과 같이 각태그별로다양한부분을뽑아낼수 있다. import urllib from BeautifulSoup import * url = raw_input('enter - ') html = urllib.urlopen(url).read() soup = BeautifulSoup(html) # Retrieve all of the anchor tags tags = soup('a') for tag in tags: # Look at the parts of a tag print 'TAG:',tag print 'URL:',tag.get('href', None) print 'Content:',tag.contents[0] print 'Attrs:',tag.attrs 상기프로그램은다음을출력합니다. python urllink2.py Enter - TAG: <a href=" Second Page</a> URL: Content: [u'\nsecond Page'] Attrs: [(u'href', u' HTML을 파싱하는데 BeautifulSoup이 가진 강력한 기능을 예제로 보여줬다. 좀더 자세한 사항은 에서 문서와 예제를 살펴보세요. 제 8 절 urllib을 사용하여 바이너리 파일 읽기 이미지나비디오 같은텍스트가아닌 (혹은바이너리)파일을 가져올때가종 종 있다. 일반적으로 이런 파일 데이터를 출력하는 것은 유용하지 않다. 하지만, urllib을사용하여,하드디스크로컬파일에 URL사본을쉽게만들수있다. 이패턴은 URL을열고, read를사용해서문서전체내용을다운로드하여문 자열변수(img)에다운로드하고,그리고나서다음과 같이정보를로컬파일에 쓴다. img = urllib.urlopen(' fhand = open('cover.jpg', 'w') fhand.write(img) fhand.close() 작성된프로그램은네트워크로모든데이터를한번에 읽어서 컴퓨터주기억장 치 img변수에저장하고, cover.jpg파일을열어디스크에데이터를쓴다. 이 방식은파일크기가사용자 컴퓨터의메모리크기보다 작다면정상적으로 작동 한다.
168 150 제 12 장. 네트워크 프로그램 하지만,오디오혹은비디오파일대용량이면,상기프로그램은멈추거나사용 자 컴퓨터메모리가부족할때극단적으로느려질수있다.메모리부족을회피 하기 위해서,데이터를블럭혹은버퍼로 가져와서,다음블럭을 가져오기전에 디스크에 각각의블럭을쓴다. 이런방식으로사용자가 가진모든메모리를사 용하지않고어떠한크기파일도 읽어올수있다. import urllib img = urllib.urlopen(' fhand = open('cover.jpg', 'w') size = 0 while True: info = img.read(100000) if len(info) < 1 : break size = size + len(info) fhand.write(info) print size,'characters copied.' fhand.close() 상기예제에서,한번에 100,000문자만 읽어오고,웹에서다음 100,000문자를 가져오기전에cover.jpg파일에 읽어온문자를쓴다. 프로그램실행 결과는다음과 같다. python curl2.py characters copied. UNIX혹은매킨토시 컴퓨터를 가지고 있다면,다음과 같이상기동작을수행하 는명령어가운영체제 자체에내장되어 있다. curl -O curl은 copy URL 의단축명령어로두예제는 curl명령어와비슷한기능을 구현해서, 사이트에 curl1.py, curl2.py 이름으로 올라가 있다.동일한 작업을좀더효과적으로수행하는 curl3.py샘플프로그 램도 있어서실무적으로 작성하는프로그램에 이런한패턴을 이용하여구현할 수 잇다. 제 9절 용어정의 BeautifulSoup: 파이썬 라이브러리로 HTML 문서를 파싱하고 브라우저가 일 반적으로생략하는 HTML의불완전한부분을보정하여 HTML문서에 서 데이터를 추출한다. 사이트에서 BeautifulSoup 코드를다운로드받을수있다. 포트(port): 서버에소켓연결을만들때,사용자가무슨 응용프로그램을연결 하는지나타내는숫자.예로,웹트래픽은통상 80포트,전자우편은 25 포트를 사용한다.
169 10. 연습문제 151 스크래핑(scraping): 프로그램이 웹브라우저를 가장하여 웹페이지를 가져와서 웹페이지의내용을 검색한다.종종프로그램이한페이지의링크를따라 다른페이지를찾게된다.그래서,웹페이지네트워크혹은소셜네트워크 전체를훑을수있다. 소켓(socket): 두 응용프로그램사이네트워크연결.두응용프로그램은양방 향으로 데이터를 주고 받는다. 스파이더(spider): 검색색인을구축하기 위해서한웹페이지를 검색하고,그웹 페이지에링크된모든페이지 검색을반복하여 인터넷에 있는 거의모든 웹페이지를 가져오기 위해서사용되는 검색엔진행동. 제 10절 연습문제 Exercise 12.1 소켓 프로그램 socket1.py을 변경하여 임의 웹페이지를 읽을 수 있도록 URL을 사용자가 입력하도록 바꾸세요. split( / )을 사용하여 URL을 컴포턴트로쪼개서소켓 connect호출에대해호스트명을추출할수있다.사 용자가적절하지못한형식혹은존재하지않는 URL을 입력하는경우를처리할 있도록 try, except를 사용하여 오류 검사기능을 추가하세요. Exercise 12.2 소켓 프로그램을 변경하여 전송받은 문자를 계수(count)하고 3000문자를출력한후에그이상텍스트출력을멈추게하세요.프로그램은전 체문서를가져와야하고,전체문자를계수(count)하고,문서마지막에문자 계수(count)결과를 출력해야 합니다. Exercise 12.3 urllib을사용하여 이전예제를반복하세요. (1)사용자가 입력 한 URL에서문서가져오기 (2) 3000문자까지화면에보여주기 (3)문서의전체 문자계수(count)하기. 이연습문제에서헤더에대해서는걱정하지말고,단지 문서본문에서첫3000문자만화면에출력하세요. Exercise 12.4 urllinks.py 프로그램을 변경하여 가져온 HTML 문서에서 문 단 (p)태그를추출하고프로그램의출력물로문단을계수(count)하고화면에 출력하세요.문단텍스트를화면에출력하지말고단지숫자만셉니다. 작성한 프로그램을 작은웹페이지뿐만아니라조금큰웹페이지에도테스트해보세요. Exercise 12.5 (고급) 소켓 프로그램을 변경하여 헤더와 빈 라인 다음에 데이터 만 보여지게 하세요. recv는 라인이 아니라 문자(새줄(newline)과 모든 문자)를 전송받는다는것을기억하세요.
170 152 제 12 장. 네트워크 프로그램
171 제 13 장 웹서비스 사용하기 프로그램을사용하여 HTTP상에서문서를 가져와서파싱하는 것이 익숙해지 면,다른프로그램(즉,브라우져에서 HTML로보여지지않는 것)에서활용되도 록특별히설계된문서를생성하는 것은그다지오래 걸리지않는다. 웹상에서데이터를교환할때두가지형식이많이사용된다. XML( extensible Markup Language )은 오랜 기간 사용되어져 왔고 문서-형식(document-style) 데이터를교환하는데 가장적합하다.딕셔너리,리스트혹은다른내부정보 를 프로그램으로 서로 교환할 때, JSON(JavaScript Object Notation, www. json.org)을 사용한다. 두 가지 형식에 대해 모두 살펴볼 것이다. 제 1절 XML(eXtensible Markup Language) XML은 HTML과 매우 유사하지만, XML이 좀더 HTML보다 구조화되었다. 여기 XML문서샘플이 있다. <person> <name>chuck</name> <phone type="intl"> </phone> < hide="yes"/> </person> 종종 XML문서를나무구조(tree structure)로생각하는 것이도움이된다.최 상단 person태그가 있고, phone 같은다른태그는부모노드의 자식(children) 노드로 표현된다.
172 154 제 13 장. 웹서비스 사용하기 Person name phone type= intl hide= yes Chuck 제 2절 XML파싱 다음은 XML을파싱하고 XML에서데이터요소를추출하는 간단한 응용프로 그램이다. import xml.etree.elementtree as ET data = ''' <person> <name>chuck</name> <phone type="intl"> </phone> < hide="yes"/> </person>''' tree = ET.fromstring(data) print 'Name:',tree.find('name').text print 'Attr:',tree.find(' ').get('hide') fromstring을 호출하여 XML 문자열 표현을 XML 노드 나무(tree) 로 변환한 다. XML이나무구조로되었을때, XML에서데이터 일부분을추출하기 위해서 호출하는 메쏘드가 연달아 있다. find함수는 XML나무를훑어서특정한태그와매칭되는노드(node)를 검색 한다. 각노드는텍스트,속성(즉, hide 같은),그리고 자식(child) 노드로구성 된다. 각노드는노드나무의최상단이될수있다. Name: Chuck Attr: yes ElementTree같은 XML파서를사용하는 것은 장점이 있다.상기예제의 XML 은매우 간단하지만,적합한 XML에관해서규칙이많이 있고, XML구문규 칙에얽매이지않고 ElementTree를사용해서 XML에서데이터를추출할수 있다. 제 3절 노드반복하기 종종 XML이다중노드를 가지고 있어서모든노드를처리하는루프를 작성할 필요가 있다. 다음 프로그램에서 모든 user 노드를 루프로 반복한다.
173 4. JSON(JavaScript Object Notation) 155 import xml.etree.elementtree as ET input = ''' <stuff> <users> <user x="2"> <id>001</id> <name>chuck</name> </user> <user x="7"> <id>009</id> <name>brent</name> </user> </users> </stuff>''' stuff = ET.fromstring(input) lst = stuff.findall('users/user') print 'User count:', len(lst) for item in lst: print 'Name', item.find('name').text print 'Id', item.find('id').text print 'Attribute', item.get('x') findall메쏘드는파이썬리스트의하위나무를 가져온다.리스트는 XML나 무에서 user 구조를 표현한다. 그리고 나서, for 루프를 작성해서 각 user 노드 값을 확인하고 name, id 텍스트 요소와 user 노드에서 x 속성도 출력한다. User count: 2 Name Chuck Id 001 Attribute 2 Name Brent Id 009 Attribute 7 제 4절 JSON(JavaScript Object Notation) JSON형식은 자바스크립트언어에서사용되는 객체와배열형식에서영감을 얻었다.하지만파이썬이 자바스크립트 이전에 개발되어서딕셔너리와리스트 의파이썬구문이 JSON구문에영향을주었다.그래서 JSON포맷이 거의파이 썬리스트와딕셔너리의조합과 일치한다. 상기 간단한 XML에대략상응하는 JSON으로 작성한 것이다음에 있다. { "name" : "Chuck", "phone" : { "type" : "intl", "number" : " " },
174 156 제 13 장. 웹서비스 사용하기 } " " : { "hide" : "yes" } 몇가지 차이점에 주목하세요. 첫째로 XML에서는 phone 태그에 intl 같은 속성을추가할수있다. JSON에서는단지키-값페어(key-value pair)다.또한 XML person 태그는 사라지고 외부 중괄호 세트로 대체되었다. 일반적으로 JSON 구조가 XML 보다 간단하다. 왜냐하면, JSON 이 XML보다 적은역량을보유하기때문이다.하지만 JSON 이딕셔너리와리스트의조합에 직접매핑된다는 장점이 있다.그리고, 거의모든프로그래밍언어가파이썬딕 셔너리와리스트에상응하는 것을 갖고 있어서, JSON 이협업하는두프로그램 사이에서데이터를교환하는매우 자연스러운형식이된다. XML에비해서상대적으로단순하기때문에, JSON 이 응용프로그램 간 거의 모든 데이터를 교환하는데 있어 빠르게 선택되고 있다. 제 5절 JSON파싱하기 딕셔너리(객체)와 리스트를 중첩함으로써 JSON을 생성한다. 이번 예제에서, user 리스트를 표현하는데, 각 user가 키-값 페어(key-value pair, 즉, 딕셔너리) 다.그래서리스트딕셔너리가 있다. 다음프로그램에서내장된 json라이브러리를사용하여 JSON을파싱하여데 이터를 읽어온다. 이것을상응하는 XML데이터,코드와비교해보세요. JSON 은조금덜정교해서사전에미리리스트를 가져오고,리스트가사용자이고, 각 사용자가키-값페어집합임을알고 있어야한다. JSON은좀더 간략(장점)하고 하지만 좀더 덜 서술적(단점)이다. import json input = ''' [ { "id" : "001", "x" : "2", "name" : "Chuck" }, { "id" : "009", "x" : "7", "name" : "Chuck" } ]''' info = json.loads(input) print 'User count:', len(info) for item in info: print 'Name', item['name'] print 'Id', item['id'] print 'Attribute', item['x']
175 6. API(Application Program Interfaces, 응용프로그램 인터페이스) 157 JSON과 XML에서 데이터를 추출하는 코드를 비교하면, json.loads()을 통해서 파이썬리스트를얻는다. for루프로파이썬리스트를훑고,리스트내부의 각 항목은파이썬딕셔너리로 각사용자별다양한정보를추출하기 위해서파이썬 인덱스 연산자를 사용한다. JSON을 파싱하면, 네이티브 파이썬 객체와 구조가 생성된다.반환된데이터가단순히네이티브파이썬구조체이기때문에,파싱된 JSON을 활용하는데 JSON 라이브러리를 사용할 필요는 없다. 프로그램출력은정확하게상기 XML버젼과동일한다. User count: 2 Name Chuck Id 001 Attribute 2 Name Brent Id 009 Attribute 7 일반적으로웹서비스에대해서 XML에서 JSON으로옮겨가는산업 경향이뚜 렷하다. JSON이프로그래밍언어에서 이미 갖고 있는네이티브 자료구조와 좀더 직접적이며 간단히 매핑되기 때문에, JSON을 사용할 때 파싱하고 데이터 추출하는코드가더욱 간단하고직접적이다.하지만 XML 이 JSON보다좀더 자기서술적이고 XML 이 강점을 가지는몇몇 응용프로그램분야가 있다.예 를들어,대부분의워드프로세서는 JSON보다는 XML을사용하여내부적으로 문서를 저장한다. 제 6 절 API(Application Program Interfaces, 응용 프로그 램 인터페이스) 이제 HTTP를사용하여 응용프로그램간에데이터를교환할수있게되었다.또 한, XML혹은 JSON을사용하여 응용프로그램간에도복잡한데이터를주고 받을수있는방법을습득했다. 다음단계는상기학습한기법을사용하여 응용프로그램 간에 계약(contract) 을 정의하고 문서화한다. 응용프로그램-대-응용프로그램 계약에 대한 일반적 명칭은 API 응용 프로그램 인터페이스(Application Program Interface) 다. API를사용할때, 일반적으로하나의프로그램이다른 응용프로그램에서사 용할수있는 가능한서비스집합을생성한다.또한,다른프로그램이서비스에 접근하여 사용할 때 지켜야하는 API (즉, 규칙 )도 게시한다. 다른프로그램에서제공되는서비스에접근을포함하여프로그램기능을 개발 할 때, 이러한 개발법을 SOA, Service-Oriented Architecture(서비스 지향 아 키텍처)라고부른다. SOA 개발방식은전반적인 응용프로그램이다른 응용 프로그램서비스를사용하는 것이다.반대로, SOA가아닌 개발방식은 응용프 로그램이하나의독립된 응용프로그램으로구현에필요한모든코드를담고 있다. 웹을사용할때SOA사례를많이찾아볼수있다.웹사이트하나를방문해서 비행기표,호텔, 자동차를단일사이트에서예약완료한다.호텔관련데이터는
176 158 제 13 장. 웹서비스 사용하기 물론항공사 컴퓨터에저장되어 있지않다.대신에항공사 컴퓨터는호텔 컴퓨터 와 계약을맺어호텔데이터를 가져와서사용자에게보여준다.항공사사이트를 통해서사용자가호텔예약을동의할 경우,항공사사이트에서호텔시스템의 또다른웹서비스를통해서실제예약을한다.전체 거래(transaction)를완료하 고 카드 결재를 진행할 때, 다른 컴퓨터가 프로세스에 관여하여 처리한다. 자동차 렌탈 서비스 호텔 예약서비스 항공 예약서비스 API API API 여행 응용프로그램 서비스 지향 아키텍쳐는 많은 장점이 있다. (1) 항상 단 하나의 데이터만 유지관 리한다. 이중으로중복예약을원치않는호텔 같은 경우에매우중요하다. (2) 데이터소유자가데이터사용에대한규칙을정한다. 이러한 장점으로, SOA시 스템은좋은성능과사용자요구를모두만족하기 위해서신중하게설계되어야 한다. 응응프로그램이웹상에 이용가능한 API로서비스집합을만들때,웹서비스 (web services)라고부른다. 제 7 절 구글 지오코딩 웹서비스(Google Geocoding Web Service) 구글이 자체적으로구축한대용량지리정보데이터베이스를누구나 이용할수 있게하는훌륭한웹서비스가 있다. Ann Arbor, MI 같은지리 검색문자열을 지오코딩 API에넣으면, 검색문자열이 의미하는지도상에 위치와근처주요 지형지물 정보를 나름 최선을 다해서 예측 제공한다. 지오코딩서비스는무료지만사용량이제한되어 있어서,상업적 응용프로그램 에 API를무제한사용할수는없다.하지만,최종사용자가 자유형식 입력박스 에 위치정보를 입력하는설문데이터가 있다면,구글 API를사용하여데이터를 깔끔하게정리하는데는 유용하다. 구글지오코딩 API 같은무료 API를사용할때, 자원사용에대한지침을준수해 야한다.너무나많은사람이서비스를남용하게되면,구글은무료서비스를중 단하거나,상당부분줄일수있다. (When you are using a free API like Google s
177 7. 구글지오코딩웹서비스(Google Geocoding Web Service) 159 geocoding API, you need to be respectful in your use of these resources. If too many people abuse the service, Google might drop or significantly curtail its free service. 서비스에대해서 자세한사항을온라인문서를정독할수있지만,무척 간단해서 브라우저에다음 URL을 입력해서테스트까지할수있다. sensor=false&address=ann+arbor%2c+mi 웹프라우저에붙여넣기전에, URL만뽑아냈고 URL에서모든 공백을제거했 는지 확인하세요. 다음은 간단한 응용프로그램이다.사용자가 검색문자열을 입력하고구글지 오코딩 API를호출하여반환된 JSON에서정보를추출한다. import urllib import json serviceurl = ' while True: address = raw_input('enter location: ') if len(address) < 1 : break url = serviceurl + urllib.urlencode({'sensor':'false', 'address': address}) print 'Retrieving', url uh = urllib.urlopen(url) data = uh.read() print 'Retrieved',len(data),'characters' try: js = json.loads(str(data)) except: js = None if 'status' not in js or js['status']!= 'OK': print '==== Failure To Retrieve ====' print data continue print json.dumps(js, indent=4) lat = js["results"][0]["geometry"]["location"]["lat"] lng = js["results"][0]["geometry"]["location"]["lng"] print 'lat',lat,'lng',lng location = js['results'][0]['formatted_address'] print location 프로그램이사용자로부터 검색문자열을받는다.적절히 인코딩된매개변수 로 검색문자열을변환하여 URL을만든다.그리고나서 urllib을사용하여구글 지오코딩 API에서텍스트를 가져온다. 고정된웹페이지와달리,반환되는데이 터는전송한매개변수와구글서버에저장된지리정보데이터에따라달라진다. JSON데이터를 가져오면, json라이브러리로파싱하고전송받은데이터가올 바른지확인하는몇가지절차를 거친후에찾고자하는정보를추출한다.
178 160 제 13 장. 웹서비스 사용하기 프로그램출력결과는다음과 같다. (몇몇 JSON출력은 의도적으로삭제했다.) $ python geojson.py Enter location: Ann Arbor, MI Retrieving geocode/json?sensor=false&address=ann+arbor%2c+mi Retrieved 1669 characters { "status": "OK", "results": [ { "geometry": { "location_type": "APPROXIMATE", "location": { "lat": , "lng": } }, "address_components": [ { "long_name": "Ann Arbor", "types": [ "locality", "political" ], "short_name": "Ann Arbor" } ], "formatted_address": "Ann Arbor, MI, USA", "types": [ "locality", "political" ] } ] } lat lng Ann Arbor, MI, USA Enter location: 다양한구글지오코딩 API의 XML과 JSON을좀더살펴보기 위해서 www. py4inf.com/code/geojson.py, py을 다운로드 받아보기 바란다. 제 8절 보안과 API사용 상용업체 API를 사용하기 위해서는 일종의 API키(API key) 가 일반적으로 필요하다.서비스제공자 입장에서누가서비스를사용하고 있으며 각사용자 가얼마나사용하고 있는를알고자한다.상용 API제공업체는서비스에대한 무료사용자와 유료사용자에대한구분을두고 있다.특정기간동안한개인 사용자가사용할수있는요청수에대해제한을두는정책을두고 있다.
179 8. 보안과 API사용 161 때때로 API키를 얻게 되면, API를 호출할 때 POST 데이터의 일부로 포함하거 나 URL의 매개변수로 키를 포함시킨다. 또다른 경우에는업체가서비스요청에대한보증을 강화해서 공유키와비밀 번호를 암호화된 메시지 형식으로 보내도록 요구한다. 인터넷을 통해서 서비스 요청을 암호화하는 일반적인 기술을 OAuth라고 한다. net사이트에서 OAuth프로토콜에대해더많은정보를만날수있다. 트위터 API가점차적으로 가치있게됨에따라트위터가 공개된 API에서 API 를매번호출할때마다 OAuth 인증을 거치도록 API를바뀌었다.다행스럽게도 편리한 OAuth라이브러리가많이 있다. 그래서명세서를 읽고아무것도없는상태에서 OAuth구현하는 것을필할수있 게 되었다. 이용 가능한 라이브러리는 복잡성도 다양한만틈 기능적으로도 다양 하다. OAuth 웹사이트에서 다양한 OAuth 라이브러리 정보를 확인할 수 있다. 다음 샘플 프로그램으로 사이트에서 twurl.py, hidden.py, oauth.py, twitter1.py 파일을 다운로드 받아서 컴퓨터 한 폴더에 저장 한다. 프로그램을사용하기 위해서트위터 계정이필요하고,파이썬코드를 응용프 로그램으로 인증하고,키,암호,토큰,토큰암호를설정해야한다. hidden.py 파일을 편집하여 4개 문자열을 파일에 적절한 변수에 저장한다. def auth() : return { "consumer_key" : "h7l...gng", "consumer_secret" : "dnk...7q", "token_key" : "101...GI", "token_secret" : "H0yM...Bo" } 트위터 웹서비스는 다음 URL을 사용하여 접근한다. json 하지만,모든비밀정보가추가되면, URL은다음과 같이보인다. &oauth_version=1.0&oauth_token=101...sgi&screen_name=drchuck &oauth_nonce= &oauth_timestamp= &oauth_signature=rlk...bod&oauth_consumer_key=h7lu...gng &oauth_signature_method=hmac-sha1 OAuth보안요구사항을충족하기 위해추가된다양한매개변수 의미를좀더 자세히알고자한다면, OAuth명세서를 읽어보기바란다. 트위터로 실행한 프로그램에서 oauth.py, twurl.py 두개 파일에 모든 복잡함을 감추었다. hidden.py에 암호를 설정해서 URL을 twurl.augment() 함수에 전송 했고, 라이브러리 코드는 URL에 필요한 매개 변수를 추가했다. twitter1.py프로그램은특정트위터사용자타임라인을 가져와서 JSON형식 문자열로반환한다.단순하게문자열의첫250문자만출력한다.
180 162 제 13 장. 웹서비스 사용하기 import urllib import twurl TWITTER_URL=' while True: print '' acct = raw_input('enter Twitter Account:') if ( len(acct) < 1 ) : break url = twurl.augment(twitter_url, {'screen_name': acct, 'count': '2'} ) print 'Retrieving', url connection = urllib.urlopen(url) data = connection.read() print data[:250] headers = connection.info().dict # print headers print 'Remaining', headers['x-rate-limit-remaining'] 프로그램을실행하면다음 결과물을출력한다. Enter Twitter Account:drchuck Retrieving [{"created_at":"sat Sep 28 17:30: "," id": ,"id_str":" ", See how the Dutch handle traffic intersections: "source":"web","truncated":false,"in_rep Remaining 178 Enter Twitter Account:fixpert Retrieving [{"created_at":"sat Sep 28 18:03: ", "id": ,"id_str":" ", "text":"3 months after my freak bocce ball accident, my wedding ring fits again! :)\n\nhttps:\/\/t.co\/2xmhpx7kgx", "source":"web","truncated":false, Remaining 177 Enter Twitter Account: 반환된타임라인데이터와함께트위터는또한 HTTP 응답헤더에요청사항에 대한 메타 데이터도 반환한다. 특히 헤더에 있는 x-rate-limit-remaining정보는 한동안서비스를 이용못하게되기전까지얼마나많은요청을할수있는가하 는정보를담고 있다. API요청을매번할때마다남은숫자가줄어드는 것을 확인할수있다. 다음예제애서,사용자의트위터 친구정보를 가져와서 JSON파싱을하고 친 구에대한정보를추출한다.파싱후에 JSON을 가져와서,좀더많은필드를 추출할때데이터를 자세히살펴보는데도움이되도록문자 4개로들여쓰기한 보기좋은출력(pretty-print) 을한다. import urllib import twurl
181 8. 보안과 API사용 163 import json TWITTER_URL = ' while True: print '' acct = raw_input('enter Twitter Account:') if ( len(acct) < 1 ) : break url = twurl.augment(twitter_url, {'screen_name': acct, 'count': '5'} ) print 'Retrieving', url connection = urllib.urlopen(url) data = connection.read() headers = connection.info().dict print 'Remaining', headers['x-rate-limit-remaining'] js = json.loads(data) print json.dumps(js, indent=4) for u in js['users'] : print u['screen_name'] s = u['status']['text'] print ' ',s[:50] JSON은중첩된파이썬리스트와딕셔너리집합이기때문에, 인덱스연산과 for루프를조합해서매우적은양의코드로반환된데이터구조를훑어볼수 있다. 프로그램 결과는 다음과 같다. (페이지에 맞도록 몇몇 데이터 항목을 줄였다.) Enter Twitter Account:drchuck Retrieving Remaining 14 { "next_cursor": , "users": [ { "id": , "followers_count": 28725, "status": { "text": "@jazzychad I just bought one..", "created_at": "Fri Sep 20 08:36: ", "retweeted": false, }, "location": "San Francisco, California", "screen_name": "leahculver", "name": "Leah Culver", }, { "id": , "followers_count": 2635, "status": { "text": Big employers like Google...", "created_at": "Sat Sep 28 19:36: ", }, "location": "Victoria Canada",
182 164 제 13 장. 웹서비스 사용하기 "screen_name": "_valeriei", "name": "Valerie Irvine", ], "next_cursor_str": " " } I just bought one.. _valeriei Big employers like Google, AT&T are h ericbollens sneak peek: my LONG take on the good &a halherzog Learning Objects is 10. We had a cake with the LO, love it! Now where so I get that "etc Enter Twitter Account: 출력마지막은 drchuck트위터 계정에서 가장최근 친구 5명을 for루프로 읽 고 친구의 가장마지막상태정보를출력한다.반환된 JSON에는 이용가능한더 많은데이터가 있다.또한,프로그램출력을보게되면,특정 계정의 find the friends 가 일정기간동안실행 가능한타임라인질의숫자와다른사용량에 제한을두고 있음을볼수있다. 이와 같은보안 API키는누가트위터 API를사용하고어느정도수준으로트위 터를사용하는지에대해서트위트가확고한신뢰를 갖게한다.사용량에한계를 두고서비스를제공하는방식은단순히 개인적인목적으로데이터 검색을할수 는 있지만,하루에수백만 API호출로데이터를추출하여제품을 개발못하게 제한하는기능도동시에한다. 제 9절 용어정의 API: 응용 프로그램 인터페이스(Application Program Interface) - 두 응용 프 로그램 컴포넌트 간에상호작용하는패턴을정의하는 응용프로그램 간의 계약. ElementTree: XML데이터를 파싱하는데 사용되는 파이썬 내장 라이브러리. JSON: JavaScript Object Notation- 자바스크립트 객체(JavaScript Objects) 구문을 기반으로 구조화된 데이터 마크업(markup)을 허용하는 형식. REST: REpresentational State Transfer - HTTP 프로토콜을 사용하여 응용 프로그램 내부에 자원에 접근을 제공하는 일종의 웹서비스 스타일. SOA: 서비스 지향 아키텍처(Service Oriented Architecture) - 응용 프로그램 이네트워크에연결된 컴포넌트로구성될때. XML: 확장 마크업 언어(eXtensible Markup Language) - 구조화된 데이터의 마크업을허용하는형식.
183 10. Exercises 165 제 10절 Exercises Exercise 13.1 데이터를 가져와서 두 문자 국가 코드를 출력하도록 www. py4inf.com/code/geojson.py혹은 정하세요.오류검사기능을추가하여국가코드가없더라도프로그램이역추 적(traceback)이 생성하지 않도록 하세요. 프로그램이 정상 작동하면, Atlantic Ocean 을검색하고어느국가에도속하지않는지역을처리할수있는지확인 하세요.
184 166 제 13 장. 웹서비스 사용하기
185 제 14 장 데이터베이스와 SQL(Structured Query Language)사용하기 제 1절 데이터베이스가뭔가요? 데이터베이스(database)는 데이터를 저장하기 위한 목적으로 조직된 파일이다. 대부분의 데이터베이스는 키(key)와 값(value)를 매핑한다는 의미에서 딕셔너 리처럼조직되었다. 가장큰차이점은데이터베이스는디스크(혹은다른영구 저장소)에 위치하고 있어서,프로그램종료후에도정보가 계속저장된다.데 이터베이스가영구저장소에저장되어서, 컴퓨터주기억장치(memory)크기에 제한받는딕셔너리보다훨씬더많은정보를저장할수있다. 딕셔너리처럼, 데이터베이스 소프트웨어는 엄청난 양의 데이터 조차도 매우 빠 르게삽입하고접근하도록설계되었다. 컴퓨터가특정항목으로빠르게찾아갈 수 있도록 데이터베이스에 인덱스(indexes)를 추가한다. 데이터베이스 소프트 웨어는 인덱스를 구축하여 성능을 보장한다. 다양한목적에맞춰서로다른많은데이터베이스시스템이 개발되어사용되고 있다. Oracle, MySQL, Microsoft SQL Server, PostgreSQL, SQLite이 여기에 포함된다. 이책에서는 SQLite를집중해서살펴볼 것이다.왜냐하면매우 일반 적인데이터베이스이며파이썬에 이미내장되어 있기때문이다. 응용프로그램 내부에서데이터베이스기능을제공하도록 SQLite가다른 응용프로그램내부 에내장(embedded)되도록설계되었다.예를들어,다른많은소프트웨어제품이 그렇듯이, 파이어폭스 브라우져도 SQLite를 사용한다. 이번 장에서 기술하는 트위터 스파이더링 응용프로그램처럼 정보과학(Informatics)에서 마주치는 몇몇 데이터 조작 문제에 SQLite가 적합하다.
186 168 제 14 장. 데이터베이스와 SQL(Structured Query Language)사용하기 제 2절 데이터베이스 개념 처음데이터베이스를볼때드는생각은마치엑셀같은다중시트를지닌스프 레드쉬트(spreadsheet)같다는 것이다. 데이터베이스에서 주요 데이터 구조물은 테이블(tables),행(rows), and열(columns)이된다. 테이블 (Table) 테이블 (Table) 행 (Row) 2.3 튜플 (Tuple) 열 (Column) 속성 (Attribute) 관계형데이터베이스의기술적인면을설명하면테이블,행,열의 개념은관계 (relation), 튜플(tuple), and 속성(attribute) 각각 형식적으로 매칭된다. 이번 장 에서는조금덜형식용어를사용한다. 제 3절 파이어폭스애드온 SQLite매니저 SQLite데이터베이스파일에 있는데이터를다루기 위해서 이번장에서주로 파이썬사용에집중을하지만,다음웹사이트에서무료로 이용 가능한 SQLite 데이터베이스 매니저(SQLite Database Manager)로 불리는 파이어폭스 애드 온(add-on)을사용해서좀더쉽게많은 작업을수행할수있다. sqlite-manager/ 브라우져를사용해서쉽게테이블을생성하고,데이터를삽입,편집하고데이 터베이스데이터에대해 간단한 SQL질의를실행할수있다. 이러한점에서데이터베이스매니저는텍스트파일을 작업할때사용하는텍스 트편집기와 유사하다.텍스트파일에하나혹은몇개 작업만수행하고자하면, 텍스트편집기에서파일을열어필요한수정작업을하고닫으면된다.텍스트 파일에 작업할사항이많은 경우는종종 간단한파이썬프로그램을 작성하여 수행한다.데이터베이스로 작업할때도동일한패턴이발견된다. 간단한 작업 은데이터베이스매니저를통해서수행하고,좀더복잡한 작업은파이썬으로 수행하는 것이 더 편리하다. 제 4절 데이터베이스테이블생성하기 데이터베이스는파이썬리스트혹은딕셔너리보다좀더명확히정의된구조를 요구한다 실질적으로 SQLite는열에저장되는데이터형식에대해서좀더많은 유연성을부여하지 만, 이번 장에서는데이터형식을엄격하게적용해서 MySQL같은다른관계형데이터베이스
187 4. 데이터베이스 테이블 생성하기 169 데이터베이스에 테이블(table)을 생성할 때, 열(column)의 명칭과 각 열(column)에저장하는테이터형식을사전에정의해야한다.데이터베이스소프트 웨어가 각열의데이터형식을 인식하게되면,데이터형식에따라데이터를 저장하고찾아오는방법을 가장효율적인방식을선택할수있다. 다음 url에서 SQLite에서지원되는다양한데이터형식을살펴볼수있다. 처음에는데이터구조를사전에정의하는 것이불편하게보이지만,대용량의데 이터가데이터베이스에포함되더라도데이터의빠른접근을보장하는 잇점이 있다. 데이터베이스파일과데이터베이스에두개의열을 가진Tracks 이름의테이블 을생성하는코드는다음과 같다. import sqlite3 conn = sqlite3.connect('music.sqlite3') cur = conn.cursor() cur.execute('drop TABLE IF EXISTS Tracks ') cur.execute('create TABLE Tracks (title TEXT, plays INTEGER)') conn.close() 연결 (connect) 연산은 현재 디렉토리 music.sqlite3 파일에 저장된 데이터 베이스에 연결(connection) 한다. 파일이 존재하지 않으면, 자동 생성된다. 연결(connection) 이라고 부르는 이유는 때때로 데이터베이스가 응용프로그램 이 실행되는 서버로부터 분리된 데이터베이스 서버(database server) 에 저 장되기때문이다.지금 간단한예제파일의 경우에데이터베이스가로컬파일 형태로파이썬코드마찬가지로동일한디렉토리에 있다. 파일을다루는파일핸들(file handle)처럼데이터베이스에저장된파일에연산 을 수행하기 위해서 커서(cursor)를 사용한다. cursor()를 호출하는 것은 개념 적으로텍스트파일을다룰때open()을호출하는 것과 개념적으로매우 유사 하다. select insert create 커 서 데이터베이스 여러분이 작성한 프로그램 커서가 생성되면, execute() 메쏘드를 사용하여 데이터베이스 콘텐츠에 명령 어실행을할수있다. 시스템에도 동일한 개념이 적용되게 한다.
188 170 제 14 장. 데이터베이스와 SQL(Structured Query Language)사용하기 데이터베이스 명령어는 특별한 언어로 표현된다. 단일 데이터베이스 언어를 학 습하도록서로다른많은데이터베이스업체사이에서표준화되었다. 데이터베이스 언어를 SQL(Structured Query Language 구조적 질의 언어)로 부른다. 상기예제에서,데이터베이스에두개의 SQL명령어를실행했다.관습적으로 데이터베이스키워드는대문자로표기한다.테이블명이나열의명칭처럼사용 자가 추가한 명령어 부분은 소문자로 표기한다. 첫 SQL명령어는만약존재한다면데이터베이스에서 Tracks테이블을삭제 한다.동일한프로그램을실행해서오류없이반복적으로 Tracks테이블을생 성하도록하는 패턴이다. DROP TABLE 명령어는 데이터베이스 테이블 및 테이블 콘텐츠전부를삭제하니주의한다. (즉, 실행취소(undo) 가없다.) cur.execute('drop TABLE IF EXISTS Tracks ') 두번째명령어는 title문자형열과 plays정수형열을 가진 Tracks으로명명 된테이블을생성한다. cur.execute('create TABLE Tracks (title TEXT, plays INTEGER)') 이제 Tracks으로명명된테이블을생성했으니, SQL INSERT연산을통해테 이블에 데이터를 넣을 수 있다. 다시 한번, 데이터베이스에 연결하여 커서 (cursor)를얻어 작업을시작한다.그리고나서 커서를사용해서 SQL명령 어를 수행한다. SQLINSERT명령어는어느테이블을사용할지특정한다.그리고나서(title, plays) 포함할필드목록과테이블새로운행에저장될 VALUES나열해서신 규 행을 정의를 마친다. 실제 값이 execute() 호출의 두번째 매개변수로 튜플( My Way, 15 ) 로넘겨는 것을표기하기 위해서 값을물음표(?,?)로명기 한다. import sqlite3 conn = sqlite3.connect('music.sqlite3') cur = conn.cursor() cur.execute('insert INTO Tracks (title, plays) VALUES (?,? )', ( 'Thunderstruck', 20 ) ) cur.execute('insert INTO Tracks (title, plays) VALUES (?,? )', ( 'My Way', 15 ) ) conn.commit() print 'Tracks:' cur.execute('select title, plays FROM Tracks') for row in cur : print row cur.execute('delete FROM Tracks WHERE plays < 100') conn.commit()
189 5. SQL(Structured Query Language)요약 171 cur.close() 먼저테이블에두개열을삽입(INSERT)하고 commit()명령어를사용하여데 이터가 데이터베이스에 저장되도록 했다. Tracks title Thunderstruck My Way plays 그리고나서, SELECT명령어를사용하여테이블에방금전에삽입한행을불 러왔다. SELECT 명령어에서 데이터를 어느 열(title, plays)에서, 어느 테이 블Tracks에서 을 가져올지명세한다. SELECT명령문을수행한후에, 커서는 for문반복을수행하는 것과 같다.효율성을 위해서, 커서가 SELECT명령문을 수행할때데이터베이스에서모든데이터를 읽지않는다.대신에 for문에서행 을 반복해서 가져하듯이 요청시에만 데이터를 읽어온다. 프로그램 실행결과는 다음과 같다. Tracks: (u'thunderstruck', 20) (u'my Way', 15) for루프가행을두개를 읽어왔다. 각각의행은 title로첫번째 값을,plays로 두번째 값을 갖는파이썬튜플이다. title문자열이 u 로시작한다고 걱정하지 마라.해당문자열은라틴문자가아닌다국어를저장할수있는 유니코드(Unicode)문자열을나타내는 것이다. 프로그램마지막에 SQL명령어를실행사용해서방금전에생성한행을모두 삭제(DELETE)했기 때문에 프로그램을 반복해서 실행할 수 있다. 삭제(DELETE) 명령어는 WHERE문을사용하여선택조건을표현할수있다.따라서명령문에 조건을충족하는행에만명령문을적용한다. 이번예제에서기준이모든행에 적용되어테이블에아무 것도없게된다.따라서프로그램을반복적으로실행할 수 있다. 삭제(DELETE)를 실행한 후에 commit()을 호출하여 데이터베이스에서 데이터를 완전히 제거했다. 제 5절 SQL(Structured Query Language)요약 지금까지, 파이썬 예제를 통해서 SQL(Structured Query Language)을 사용했 고, SQL명령어에대한기본을다루었다. 이번 장에서는 SQL언어를보고 SQL 구문 개요를살펴본다. 대단히 많은 데이터베이스 업체가 존재하기 때문에 호환성의 문제로 SQL(Structured Query Language)이 표준화되었다. 그래서, 여러 업체가 개 발한데이터베이스시스템사이에호환하는방식으로 커뮤니케이션 가능하다.
190 172 제 14 장. 데이터베이스와 SQL(Structured Query Language)사용하기 관계형 데이터베이스는 테이블, 행과 열로 구성된다. 열(column)은 일반적으 로텍스트,숫자,혹은날짜 자료형을 갖는다.테이블을생성할때,열의명칭과 자료형을지정한다. CREATE TABLE Tracks (title TEXT, plays INTEGER) 테이블에 행을 삽입하기 위해서 SQL INSERT 명령어를 사용한다. INSERT INTO Tracks (title, plays) VALUES ('My Way', 15) INSERT문장은테이블 이름을명기한다.그리고나서새로운행에놓고자하는 열/필드 리스트를 명시한다. 그리고 나서 키워드 VALUES와 각 필드 별로 해당하 는 값을넣는다. SQL SELECT명령어는데이터베이스에서행과열을 가져오기 위해사용된다. SELECT명령문은 가져오고자하는행과 WHERE절을사용하여어느행을 가져 올지지정한다.선택사항으로 ORDER BY절을 이용하여반환되는행을정렬할 수도 있다. SELECT * FROM Tracks WHERE title = 'My Way' * 을사용하여 WHERE절에매칭되는 각행의모든열을데이터베이스에서 가져 온다. 주목할점은파이썬과달리 SQL WHERE절은등식을시험하기 위해서두개의 등치기호대신에단일등치기호를사용한다. WHERE에서 인정되는다른논리 연산자는<, >, <=, >=,!= 이고,논리표현식을생성하는데AND, OR,괄호를사용 한다. 다음과 같이반환되는행이필드값중하나에따라정렬할수도 있다. SELECT title,plays FROM Tracks ORDER BY title 행을제거하기 위해서, SQL DELETE문장에 WHERE절이필요하다. WHERE절이 어느 행을 삭제할지 결정한다. DELETE FROM Tracks WHERE title = 'My Way' 다음과 같이 SQL UPDATE 문장을 사용해서 테이블에 하나 이상의 행 내에 있는 하나 이상의 열을 갱신(UPDATE)할 수 있다. UPDATE Tracks SET plays = 16 WHERE title = 'My Way' UPDATE문장은먼저테이블을명시한다.그리고나서, SET키워드다음에변경 할필드리스트와값을명시한다.그리고선택사항으로 갱신될행을WHERE절에 지정한다.단일 UPDATE문장은 WHERE절에서매칭되는모든행을 갱신한다.혹 은 만약 WHERE절이 지정되지 않으면,테이블 모든 행에 대해서 갱신(UPDATE)을 한다. 네가지 기본 SQL 명령문(INSERT, SELECT, UPDATE, DELETE)은 데이터 를 생성하고 유지 관리하는데 필요한 기본적인 4가지 작업을 가능케 한다.
191 6. 데이터베이스를 사용한 트위터 스파이더링(Spidering) 173 제 6 절 데이터베이스를 사용한 트위터 스파이더링(Spidering) 이번장에서트위커 계정을조사하고데이터베이스를생성하는 간단한스파이 더링프로그램을 작성합니다.주의:프로그램을실행할때매우주의하세요.여 러분의트위터 계정접속이차단될정도로너무많은데이터를 가져오거나 장 시간프로그램을실행하지마세요. 임의 스파이더링 프로그램이 가지는 문제점 중의 하나는 종종 중단되거나 여러 번 재시작할필요가생긴다는 것이다. 이로사유로지금까지 가져온데이터를 잃을수도 있다는 것이다.데이터 가져오기온처음시점에서항상다시시작하고 싶지는않다.그래서데이터를 가져오면저장하길원한다.프로그램이 자동으로 백업작업을 수행해서 중단된 곳에서부터 다시 가져오는 작업을 했으면 한다. 출발은한사람의트위터 친구와상태정보를 가져오는 것에서시작한다.그리 고, 친구리스트를반복하고,향후에 가져올수있도록 친구 각각을데이터베이 스에추가한다.한사람의트위터 친구를처리한후에,테이터베이스를확인하 고 친구의 친구한명을 가져온다. 이것을반복적으로수행하고, 방문하지않는 (unvisited) 친구를 선택하고,친구의 리스트를 가져온다. 그리고 향후 방문을 위해서 현재 리스트에서 보지 않은 친구를 추가한다. 인기도(popularity) 를 측정하도록 데이터베이스에 특정 친구를 얼마나 자주 봤는지를 기록한다. 알고 있는 계정리스트를저장함으로써,혹은 계정을 가져왔는혹은그렇지않은 지,그리고 계정이 컴퓨터하드디스크데이터베이스에서얼마나 인기있는지에 따라원하는만큼프로그램을멈추거나다시시작할수있다. 프로그램이약간복잡하다.트위터 API를사용한책의앞선예제에서 가져온 코드에 기반하여 작성되었다. 다음이 트위터 스파이더링 응용프로그램 소스코드다. import urllib import twurl import json import sqlite3 TWITTER_URL = ' conn = sqlite3.connect('spider.sqlite3') cur = conn.cursor() cur.execute(''' CREATE TABLE IF NOT EXISTS Twitter (name TEXT, retrieved INTEGER, friends INTEGER)''') while True: acct = raw_input('enter a Twitter account, or quit: ') if ( acct == 'quit' ) : break if ( len(acct) < 1 ) :
192 174 제 14 장. 데이터베이스와 SQL(Structured Query Language)사용하기 cur.execute('select name FROM Twitter WHERE retrieved = 0 LIMIT 1') try: acct = cur.fetchone()[0] except: print 'No unretrieved Twitter accounts found' continue url = twurl.augment(twitter_url, {'screen_name': acct, 'count': '20'} ) print 'Retrieving', url connection = urllib.urlopen(url) data = connection.read() headers = connection.info().dict # print 'Remaining', headers['x-rate-limit-remaining'] js = json.loads(data) # print json.dumps(js, indent=4) cur.execute('update Twitter SET retrieved=1 WHERE name =?', (acct, ) ) countnew = 0 countold = 0 for u in js['users'] : friend = u['screen_name'] print friend cur.execute('select friends FROM Twitter WHERE name =? LIMIT 1', (friend, ) ) try: count = cur.fetchone()[0] cur.execute('update Twitter SET friends =? WHERE name =?', (count+1, friend) ) countold = countold + 1 except: cur.execute('''insert INTO Twitter (name, retrieved, friends) VALUES (?, 0, 1 )''', ( friend, ) ) countnew = countnew + 1 print 'New accounts=',countnew,' revisited=',countold conn.commit() cur.close() 데이터베이스는 spider.sqlite3 파일에 저장되어 있다. 테이블 이름은 Twitter다. Twitter테이블은 계정 이름에대한열, 계정 친구정보를 가져 왔는지여부를나타내는열,그리고 계정이얼마나많이 친구추가(friended) 되었는가 나타내는 열로 구성되었다. 프로그램의메인루프에서,사용자가트위터 계정 이름을 입력하거나프로그램 에서나가기 위해 끝내기(quit) 를 입력한다.사용자가트위터 계정을 입력하 면, 친구리스트와상태정보도 가져온다.만약데이터베이스에존재하지않다면 데이터베이스에 친구로추가한다.만약 친구가 이미리스트에존재한다면,데이 터베이스 행으로 friends 필드에 추가한다. 만약사용자가엔터키를누르면,아직 가져오지않은다음트위터 계정에대 해서데이터베이스정보를살펴본다.그계정의 친구와상태정보를 가져오고, 데이터베이스에 추가하거나 갱신하고, friends count를 증가한다.
193 6. 데이터베이스를 사용한 트위터 스파이더링(Spidering) 175 친구리스트와상태정보를 가져왔으면,반환된 JSON형식user항목을반복돌 려 각사용자의 screen_name을 가져온다.그리고나서 SELECT 문을사용하여 데이터베이스에 screen_name이 저장되었는지, 레코드가 존재하면 친구 숫자 (friends)를 확인한다. countnew = 0 countold = 0 for u in js['users'] : friend = u['screen_name'] print friend cur.execute('select friends FROM Twitter WHERE name =? LIMIT 1', (friend, ) ) try: count = cur.fetchone()[0] cur.execute('update Twitter SET friends =? WHERE name =?', (count+1, friend) ) countold = countold + 1 except: cur.execute('''insert INTO Twitter (name, retrieved, friends) VALUES (?, 0, 1 )''', ( friend, ) ) countnew = countnew + 1 print 'New accounts=',countnew,' revisited=',countold conn.commit() 커서가 SELECT문을수행하면행을 가져온다. for문으로동일한 작업을할수 있지만,단지하나의행(LIMIT 1)만을 가져오기때문에,SELECT처리 결과에서 첫번째만 가져오는 fetchone() 메쏘드를 사용한다. fetchone()은 설사 하나 의 필드만 있더라도 행을 튜플(tuple)로 반환하기 때문에, [0]을 사용해서 튜플 로부터첫번째 값을얻어count변수에현재 친구숫자를구한다. 정상적으로데이터를 가져오면, SQLWHERE절을 가진UPDATE문을사용하여 친 구의 계정에매칭되는행에대해서 friends열에추가한다. SQL에두개의플 레이스홀더(placeholder, 물음표)가 있고, execute()의 두 매개변수가 물음표 자리에 SQL 안으로 치환될 값을 가진 두-요소 튜플이 된다. 만약try블록에서코드가 작동하지않는다면,아마도SELECT문의WHERE name =?절에서매칭되는레코드가없기때문이다.그래서, except블록에서, SQL INSERT문을사용하여 screen_name을 가져온적이없고 친구숫자를 0 으로 설정해서 친구의screen_name을테이블에추가한다. 처음프로그램을실행하고트위터 계정을 입력하면,프로그램이다음과 같이 실행된다. Enter a Twitter account, or quit: drchuck Retrieving New accounts= 20 revisited= 0 Enter a Twitter account, or quit: quit 프로그램을 처음으로 실행하여서, 데이터베이스는 비여 있다. spider.sqlite3 파일에 데이터베이스를 생성하고, Twitter 이름의 테이블을 추가한다. 그리고 나서 친구몇명을 가져온다.데이터베이스가비여있기때문에모든 친구를추 가한다.
194 176 제 14 장. 데이터베이스와 SQL(Structured Query Language)사용하기 이지점에서spider.sqlite3파일에무엇이 있는지를살펴보기 위해서 간단한 데이터베이스 덤퍼(dumper)를 작성한다. import sqlite3 conn = sqlite3.connect('spider.sqlite3') cur = conn.cursor() cur.execute('select * FROM Twitter') count = 0 for row in cur : print row count = count + 1 print count, 'rows.' cur.close() 상기프로그램은데이터베이스를열고 Twitter테이블의모든행과열을선택 하고루프를모든행에대해돌려행별로출력한다. 앞서 작성한트위터스파이더를실행한후에 이프로그램을실행하면,출력 결 과는다음과 같다. (u'opencontent', 0, 1) (u'lhawthorn', 0, 1) (u'steve_coppin', 0, 1) (u'davidkocher', 0, 1) (u'hrheingold', 0, 1) rows. 각screen_name에대해한행만 있다.screen_name데이터를 가져오지않아서 데이터베이스에 있는 모든 사람은 친구가 한명 뿐이다. 이제데이터베이스가트위터 계정 (drchuck)에서 친구정보를 가져온 것을확 인했다.프로그램을반복적으로실행해서,다음과 같이트위터 계정을 입력하는 대신에 엔터키를 눌러 처리되지 않은 다음 계정 친구정보를 가져오게 한다. Enter a Twitter account, or quit: Retrieving New accounts= 18 revisited= 2 Enter a Twitter account, or quit: Retrieving New accounts= 17 revisited= 3 Enter a Twitter account, or quit: quit 엔터키를누를때(즉,트위터 계정을명시하지않았을때),다음코드가수행 된다. if ( len(acct) < 1 ) : cur.execute('select name FROM Twitter WHERE retrieved = 0 LIMIT 1') try: acct = cur.fetchone()[0] except: print 'No unretrieved twitter accounts found' continue
195 6. 데이터베이스를 사용한 트위터 스파이더링(Spidering) 177 SQL SELECT문을 사용해서 첫 사용자(LIMIT 1) 이름을 가져온다. 사용자 를 가져왔는가 의 값은여전히 0으로설정되어 있다. try/except블록내부에 fetchone()[0] 패턴을 사용하여 가져온 데이터에서 screen_name을 추출하던 가혹은오류메시지를출력하고다시돌아간다. 처리되지않은 screen_name을성공적으로 가져오면,다음과 같이데이터를 가 져온다. url = twurl.augment(twitter_url, {'screen_name': acct, 'count': '20'} ) print 'Retrieving', url connection = urllib.urlopen(url) data = connection.read() js = json.loads(data) cur.execute('update Twitter SET retrieved=1 WHERE name =?', (acct, ) ) 데이터를 성공적으로 가져오면 UPDATE문을 사용하여 이 계정의 친구 가져오기 를 완료했는지 표기하기 위해서 retrieved 열에 1 을 표시한다. 이렇게 함으로 써반복적으로동일한데이터를 가져오지않게하고트위터 친구네트워크를 타고앞으로나갈수있게한다. 친구프로그램을실행하고다음방문하지않은 친구의 친구정보를 가져오기 위해서두번엔터를누르고, 결과값을확인하는프로그램을실행하면,다음출 력값을얻게된다. (u'opencontent', 1, 1) (u'lhawthorn', 1, 1) (u'steve_coppin', 0, 1) (u'davidkocher', 0, 1) (u'hrheingold', 0, 1)... (u'cnxorg', 0, 2) (u'knoop', 0, 1) (u'kthanos', 0, 2) (u'lecturetools', 0, 1) rows. lhawthorn과 opencontent을방문한 이력이 잘기록됨을볼수있다. cnxorg 과 kthanos 계정은 이미 두 명의 팔로워(follower)가 있다. 친구 세명(drchuck, opencontent,lhawthorn)을 가져와서,테이블은 55 친구행이생겼다. 매번프로그램을실행하고엔터키를누를때마다,다음방문하지않은(예,다음 계정은 steve_coppin) 계정을 선택해서, 친구 목록을 가져오고, 가져온 것으로 표기하고, steve_coppin 친구 각각을 데이터베이스 끝에 추가하고 데이터베이 스에 이미추가되어 있으면 친구숫자를 갱신한다. 프로그램의 데이터가 모두 데이터베이스 디스크에 저장되어서, 스파이더링을 잠시보류할수있ek.데이터손실없이원하는만큼다시시작할수있다.
196 178 제 14 장. 데이터베이스와 SQL(Structured Query Language)사용하기 제 7절 데이터모델링기초 관계형데이터베이스의진정한힘은다중테이블과테이블사이의관계를생 성할때생긴다. 응용프로그램데이터를쪼개서다중테이블과두테이블 간에 관계를 설정하는 것을 데이터 모델링(data modeling)이라고 한다. 테이블 정보 와 테이블 관계를 표현하는 설계 문서를 데이터 모델(data model)이라고 한다. 데이터 모델링(data modeling)은 상대적으로 고급 기술이여서 이번 장에서는 관계형데이터모델링의 가장기본적인 개념만을소개한다.데이터모델링에 대한좀더 자세한사항은다음링크에서시작해볼수있다. 트위터스파이더 응용프로그램으로단순히한사람의 친구가몇명인지세는 대신에,모든관계리스트를 가지고서특정 계정에팔로잉하는모든사람을찾 는다. 모두팔로잉하는 계정을많이 가지고 있어서,트위터(Twitter)테이블에단순 히하나의열만을추가해서는해결할수없다.그래서 친구를짝으로추적할 수 있는새로운테이블을생성한다.다음이 간단하게상기테이블을생성하는 방식이다. CREATE TABLE Pals (from_friend TEXT, to_friend TEXT) drchuck을팔로잉하는사람을마주칠때마다,다음과 같은형식의행을삽입 한다. INSERT INTO Pals (from_friend,to_friend) VALUES ('drchuck', 'lhawthorn') drchuck 트위터 피드에서 친구 20명을 처리하면서, drchuck 을 첫 매개변수 로 가지는 20개레코드를삽입해서데이터베이스에중복되는많은문자열이 생길 것이다. 문자열 데이터 중복은 데이터베이스 정규화(database normalization) 모범 사 례(berst practice)를 위반하게 만든다. 기본적으로 데이터베이스 정규화는 데이 터베이스에 결코한번 이상동일한문자열을저장하지않는다.만약한번 이상 데이터가 필요하다면, 그 특정 데이터에 대한 숫자 키(key)를 생성하고, 그 키를 사용하여실제데이터를참조한다. 실무에서,문자열이 컴퓨터주기억장치나디스크에저장되는정수형 자료보다 훨씬많은 공간을차지하고더많은처리시간이비교나정렬에소요된다.항목 이단지수백개라면,저장소나처리시간이그다지문제되지않는다.하지만, 데이터베이스에수백만명의사람정보와 1억건 이상의링크가 있다면, 가능한 빨리데이터를스캔하는 것이정말중요하다. 앞선예제에서사용된Twitter테이블대신에People로명명된테이블에트위 커 계정을저장한다. People테이블은트위터사용자에대한행과관련된숫자 키를저장하는추가열(column)이 있다. SQLite는데이터열의특별한 자료형 (INTEGER PRIMARY KEY)을 이용하여 테이블에 삽입할 임의 행에 대해서 자동 적으로키값을추가하는기능이 있다.
197 8. 다중테이블을 가지고프로그래밍 179 다음과 같이추가적인id열을 가진People테이블을생성할수있다. CREATE TABLE People (id INTEGER PRIMARY KEY, name TEXT UNIQUE, retrieved INTEGER) People테이블의 각행에서 친구숫자를더이상 유지관리하고 있지않음을주 목하세요. id 열 자료형으로 INTEGER PRIMARY KEY 선택할 때 함축되는 의미는 다음과 같다.,사용자가삽입하는 각행에대해서 SQLite가 자동으로 유일한숫 자 키를 할당하고 관리하게 한다. UNIQUE 키워드를 추가해서 SQLite에 name에 동일한 값을 가진두행을삽입하지못하게한다. 상기Pals테이블을생성하는대신에,데이터베이스에from_id,to_id두정수 자료형 열을 지닌 Follows 테이블을 생성한다. Follows 테이블은 from_id과 to_id의조합 으로테이블이 유일하다는제약사항도 가진다. (즉,중복된행을 삽입할수없다.) CREATE TABLE Follows (from_id INTEGER, to_id INTEGER, UNIQUE(from_id, to_id) ) 테이블에 UNIQUE절을추가한다는 의미는레코드를삽입할때데이터베이스에 서지켜야하는규칙집합을 의사소통하는 것이다. 잠시후에보겠지만,프로그 램상에편리하게 이러한규칙을생성한다. 이러한규칙집합은실수를방지하게 하고코드를 작성을 간결하게한다. 본질적으로 Follows 테이블을 생성할 때, 관계(relationship) 를 모델링하여 한사람이다른사람을 팔로우(follow) 하고 이것을 (a)사람이연결되어 있고, (b)관계을방향성이나타나도록숫자를짝지어표현한다. Follows from_id to_id People id name drchuck opencontent lhawthorn steve_coppin... retrieved 제 8절 다중테이블을 가지고프로그래밍 테이블두개,주키(primary key)와앞서설명된참조키를사용하여트위터스 파이더링 프로그램을 다시 작성한다. 다음은 새로운 버젼 프로그램 코드다.
198 180 제 14 장. 데이터베이스와 SQL(Structured Query Language)사용하기 import urllib import twurl import json import sqlite3 TWITTER_URL = ' conn = sqlite3.connect('friends.sqlitesqlite3') cur = conn.cursor() cur.execute('''create TABLE IF NOT EXISTS People (id INTEGER PRIMARY KEY, name TEXT UNIQUE, retrieved INTEGER)''') cur.execute('''create TABLE IF NOT EXISTS Follows (from_id INTEGER, to_id INTEGER, UNIQUE(from_id, to_id))''') while True: acct = raw_input('enter a Twitter account, or quit: ') if ( acct == 'quit' ) : break if ( len(acct) < 1 ) : cur.execute('''select id, name FROM People WHERE retrieved = 0 LIMIT 1''') try: (id, acct) = cur.fetchone() except: print 'No unretrieved Twitter accounts found' continue else: cur.execute('select id FROM People WHERE name =? LIMIT 1', (acct, ) ) try: id = cur.fetchone()[0] except: cur.execute('''insert OR IGNORE INTO People (name, retrieved) VALUES (?, 0)''', ( acct, ) ) conn.commit() if cur.rowcount!= 1 : print 'Error inserting account:',acct continue id = cur.lastrowid url = twurl.augment(twitter_url, {'screen_name': acct, 'count': '20'} ) print 'Retrieving account', acct connection = urllib.urlopen(url) data = connection.read() headers = connection.info().dict print 'Remaining', headers['x-rate-limit-remaining'] js = json.loads(data) # print json.dumps(js, indent=4) cur.execute('update People SET retrieved=1 WHERE name =?', (acct, ) ) countnew = 0 countold = 0
199 8. 다중테이블을 가지고프로그래밍 181 for u in js['users'] : friend = u['screen_name'] print friend cur.execute('select id FROM People WHERE name =? LIMIT 1', (friend, ) ) try: friend_id = cur.fetchone()[0] countold = countold + 1 except: cur.execute('''insert OR IGNORE INTO People (name, retrieved) VALUES (?, 0)''', ( friend, ) ) conn.commit() if cur.rowcount!= 1 : print 'Error inserting account:',friend continue friend_id = cur.lastrowid countnew = countnew + 1 cur.execute('''insert OR IGNORE INTO Follows (from_id, to_id) VALUES (?,?)''', (id, friend_id) ) print 'New accounts=',countnew,' revisited=',countold conn.commit() cur.close() 프로그램이다소복잡해보인다.하지만,테이블을연결하기 위해서정수형키 를사용하는패턴을보여준다.기본적인패턴은다음과 같다. 1. 주키(primary key)와 제약 사항을 가진 테이블을 생성한다. 2. 사람(즉, 계정 이름)에대한논리키가필요할때사람에대한id 값이필요 하다. 사람 정보가 이미 People 테이블에 존재하는지에 따라, (1) People 테이블에사람을찾아서그사람에대한 id 값을 가져오거나, (2)사람을 People 테이블에 추가하고 신규로 추가된 행의 id 값을 가져온다. 3. 팔로우(follow) 관계를 잡아내는 행을 추가한다. 이들 각각을순서대로다룰 것이다. 8.1 데이터베이스테이블의제약사항 테이블구조를설계할때,데이터베이스시스템에몇가지규칙을설정할수있 다. 이러한규칙은실수를방지하고 잘못된데이터가테이블에들어가는 것을 막는다.테이블을생성할때: cur.execute('''create TABLE IF NOT EXISTS People (id INTEGER PRIMARY KEY, name TEXT UNIQUE, retrieved INTEGER)''') cur.execute('''create TABLE IF NOT EXISTS Follows (from_id INTEGER, to_id INTEGER, UNIQUE(from_id, to_id))''') People 테이블에 name 칼럼이 유일(UNIQUE)함을 나타낸다. Follows 테이블 의 각행에서두숫자조합은 유일하다는 것도나타낸다.하나 이상의동일한 관계를추가하는 것 같은실수를 이러한제약사항을통해서방지한다.
200 182 제 14 장. 데이터베이스와 SQL(Structured Query Language)사용하기 다음 코드에서 이런 제약사항의 장점을 확인할 수 있다. cur.execute('''insert OR IGNORE INTO People (name, retrieved) VALUES (?, 0)''', ( friend, ) ) INSERT문에 OR IGNORE절을추가해서만약특정 INSERT가 name이 유일 (unique)해야 한다 를 위반하게 되면, 데이터베이스 시스템은 INSERT를 무시한 다. 데이터베이스 제약 사항을 안전망으로 사용해서 무언가가 우연히 잘못되지 않게방지한다. 마찬가지로, 다음 코드는 정확히 동일 Follows관계를 두번 추가하지 않는다. cur.execute('''insert OR IGNORE INTO Follows (from_id, to_id) VALUES (?,?)''', (id, friend_id) ) 다시한번,Follows행에대해지정한 유일한제약사항을 위반하게되면INSERT 시도를 무시하도록 데이터베이스에 지시한다. 8.2 레코드를 가져오거나 삽입하기 사용자가트위터 계정을 입력할때,만약 계정이존재한다면, id 값을찾아야 한다.만약 People테이블에 계정이존재하지않는다면,레코드를삽입하고삽 입된행에서id 값을얻어와야한다. 이것은매우 일반적인패턴이고,상기프로그램에서두번수행되었다. 가져온 트위터 JSON 사용자(user) 노드에서 screen_name을 추출할 때, 친구 계정의 id를어떻게찾는지코드가보여준다. 시간이지남에따라점점더많은 계정이데이터베이스에존재할 것 같기때문 에, SELECT문을 사용해서 People 레코드가 존재하는지 먼저 확인한다. try구문내에서모든 것이정상적으로 잘 작동하면 2, fetchone()을사용하여 레코드를 가져와서,반환된튜플의첫번째요소만 읽어오고 friend_id에저장 한다. 만약 SELECT가 실패하면, fetchone()[0] 코드도 실패하고 제어권은 except 블록으로 이관된다. friend = u['screen_name'] cur.execute('select id FROM People WHERE name =? LIMIT 1', (friend, ) ) try: friend_id = cur.fetchone()[0] countold = countold + 1 except: cur.execute('''insert OR IGNORE INTO People (name, retrieved) VALUES (?, 0)''', ( friend, ) ) conn.commit() if cur.rowcount!= 1 : 2 일반적으로,문장이 만약모든것이 잘된다면 으로시작하면,코드는필히 try/except를필 요로한다.
201 8. 다중테이블을 가지고프로그래밍 183 print 'Error inserting account:',friend continue friend_id = cur.lastrowid countnew = countnew + 1 except코드에서끝나게되면,행을찾지못해서행을삽입해야한다는 의미가 된다. INSERT OR IGNORE를 사용해서 오류를 피하고 데이터베이스에 진정으로 갱신하기 위해서 commit()을 호출한다. 데이터베이스에 쓰기가 수행된 후에, 얼마나많은행이영향을받았는지확인하기 위해서cur.rowcount로확인한다. 단일행을삽입하려고했는데,영향을받은행의숫자가 1과다르다면,그것은 오류다. 삽입(INSERT)이 성공하면, cur.lastrowid를 살펴보고 신규로 생성된 행의 id 칼럼에무슨 값이대입되었는지알수있다. 8.3 친구관계저장하기 트위터사용자와 JSON 친구에대한키값을알게되면,다음코드로두개의숫 자를 Follows 테이블에 삽입하는 것은 간단하다. cur.execute('insert OR IGNORE INTO Follows (from_id, to_id) VALUES (?,?)', (id, friend_id) ) 데이터베이스를 생성할 때 유일(unique)한 제약조건과 INSERT문에 OR IGNORE 을추가함으로써데이터베이스스스로관계를두번삽입하는 것을방지하도록 한 것에주목한다. 다음에 프로그램의 샘플 실행 결과가 있다. Enter a Twitter account, or quit: No unretrieved Twitter accounts found Enter a Twitter account, or quit: drchuck Retrieving New accounts= 20 revisited= 0 Enter a Twitter account, or quit: Retrieving New accounts= 17 revisited= 3 Enter a Twitter account, or quit: Retrieving New accounts= 17 revisited= 3 Enter a Twitter account, or quit: quit drchuck 계정으로시작해서,프로그램이 자동적으로다음두개의 계정을선택 해서 데이터베이스에 추가한다. 다음은프로그램수행을완료한후에 People과 Follows테이블에첫몇개의 행이다. People: (1, u'drchuck', 1) (2, u'opencontent', 1) (3, u'lhawthorn', 1)
202 184 제 14 장. 데이터베이스와 SQL(Structured Query Language)사용하기 (4, u'steve_coppin', 0) (5, u'davidkocher', 0) 55 rows. Follows: (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) 60 rows. People 테이블의 id, name, visited 필드와 Follows 테이블 양 끝에 관계 숫자 를볼수있다. People테이블에서,사람첫세명을방문해서,데이터를 가져온 것을볼수있다.Follows테이블의데이터는drchuck(사용자 1)이첫다섯개행 에보여진모든사람에대해 친구임을나타낸다. 이것은당연한데왜냐하면처음 가져와서 저장한 데이터가 drchuck의 트위터 친구들이기 때문이다. Follows 테이블에서좀더많은행을출력하면,사용자 2, 3혹은그이상의 친구를볼수 있다. 제 9절 세종류의키 지금까지데이터를다중연결된테이블에넣고키(keys)를사용하여행을연 결하는방식으로데이터모델을생성했는데,키와관련된몇몇용어를살펴볼 필요가 있다. 일반적으로데이터베이스모델에서세가지종류의키가사용된다. 논리키(logical key)는 실제세상 이행을찾기 위해서사용하는키 다. 데이터 모델 예제에서, name 필드는 논리키다. 사용자에 대해서 screen_name이고, name 필드를 사용하여 프로그램에서 여러번 사용자 행을찾을수있다.논리키에 UNIQUE제약사항을추가하는 것이 의미 있다는 것을종종 이해하게된다.논리키는어떻게바깥세상에서행을 찾는지다루기때문에,테이블에동일한 값을 가진다중행이존재한다는 것은 의미가없다. 주키(primary key)는 통상적으로 데이터베이스에서 자동 대입되는 숫자 다.프로그램밖에서는 일반적으로 의미가없고,단지서로다른테이블에 서행을열결할때만사용된다.테이블에행을찾을때,통상적으로주키를 사용해서행을찾는 것이 가장빠르게행을찾는방법이다.주키는정수형 이어서,매우적은저장공간을차지하고매우빨리비교혹은정렬할수 있다. 이번에사용된데이터모델에서id필드가주키의한예가된다. 외부 키(foreign key)는 일반적으로 다른 테이블에 연관된 행의 주키 를 가리키는숫자다. 이번에사용된데이터모델의외부키의사례는 from_id다. 주키 id필드명을 호출하고, 항상 외부키에 임의 필드명에 접미사로_id 붙이는 명명규칙을사용한다.
203 10. JOIN을 사용하여 데이터 가져오기 185 제 10절 JOIN을사용하여데이터 가져오기 데이터정규화규칙을따라서,데이터를주키와외부키로연결된두개의테이 블로나누어서,테이블데이터를다시합치기 위해서 SELECT를 작성할필요가 있다. SQL은JOIN절을사용해서테이블을다시연결한다.JOIN절에서테이블사이의 행을다시연결할필드를지정한다. 다음은JOIN절을 가진SELECT예제이다. SELECT * FROM Follows JOIN People ON Follows.from_id = People.id WHERE People.id = 1 JOIN절은 Follows와 People 테이블에서 선택하는 필드를 나타낸다. ON절은 어 떻게두테이블이합쳐지는지를나타낸다.Follows에서행을선택하고People 에서행을추가하는데,Follows테이블의from_id와People테이블의id 값은 동일하다. People id name drchuck opencontent lhawthorn steve_coppin... retrieved Follows from_id to_id name id from_id drchuck drchuck drchuck to_id name opencontent lhawthorn steve_coppin JOIN 결과는People테이블필드와Follows테이블에서매칭되는필드를 가진 메타-행(meta-row) 을 생성한다. People 테이블 id 필드와 Follows 테이블 from_id사이에하나 이상의매칭이존재한다면, JOIN은필요하면데이터를 중복하면서, 행에 매칭되는 짝 각각에 대해 메타-행을 생성한다. 다중테이블트위터프로그램을수차례수행한후에데이터베이스에 있는데이 터를 가지고다음코드가시연한다. import sqlite3 conn = sqlite3.connect('spider.sqlite3') cur = conn.cursor() cur.execute('select * FROM People') count = 0 print 'People:' for row in cur :
204 186 제 14 장. 데이터베이스와 SQL(Structured Query Language)사용하기 if count < 5: print row count = count + 1 print count, 'rows.' cur.execute('select * FROM Follows') count = 0 print 'Follows:' for row in cur : if count < 5: print row count = count + 1 print count, 'rows.' cur.execute('''select * FROM Follows JOIN People ON Follows.from_id = People.id WHERE People.id = 2''') count = 0 print 'Connections for id=2:' for row in cur : if count < 5: print row count = count + 1 print count, 'rows.' cur.close() 이프로그램에서 People과 Follows테이블을먼저보여주고,함께 JOIN된데 이터 일부분을보여준다. 다음이프로그램출력이다. python twjoin.py People: (1, u'drchuck', 1) (2, u'opencontent', 1) (3, u'lhawthorn', 1) (4, u'steve_coppin', 0) (5, u'davidkocher', 0) 55 rows. Follows: (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) 60 rows. Connections for id=2: (2, 1, 1, u'drchuck', 1) (2, 28, 28, u'cnxorg', 0) (2, 30, 30, u'kthanos', 0) (2, 102, 102, u'somethinggirl', 0) (2, 103, 103, u'ja_pac', 0) 20 rows. People과 Follows테이블에서 칼럼을볼수있고,마지막행의집합은 JOIN 절을 가진SELECT문의 결과다. 마지막 SELECT문에서, opencontent (즉 People.id=2)를 친구로 가진 계정을 찾는다.
205 11. 요약 187 마지막 SELECT 메타-행 의 각각에서첫두열은 Follows테이블에서, 3번째 부터 5번째 열은 People 테이블에서 가져왔다. 두번째 열(Follows.to_id)과 세번째 열(People.id)은 join된 메타-열 에서 매칭됨을 볼 수 있다. 제 11절 요약 이번 장은 파이썬에서 데이터베이스 사용 기본적인 개요에 대해 폭넓게 다루었 다. 데이터를 저장하기 위해서 파이썬 딕셔너리나 일반적인 파일보다 데이터베 이스를사용하여코드를 작성하는 것이훨씬복잡하다.그래서,만약 작성하는 응용프로그램이실질적으로데이터베이스역량을필요하지않는다면굳이데 이터베이스를사용할 이유는없다.데이터베이스가특히 유용한상황은 (1)큰 데이터셋에서 작은 임의적인 갱신이많이필요한 응용프로그램을 작성할때(2) 데이터가너무 커서딕셔너리에담을수없고반복적으로정보를 검색할때, (3)한번실행에서다음실행때까지데이터를보관하고,멈추고, 재시작하는데 매우긴실행프로세스를 갖는 경우다. 많은 응용프로그램요구사항을충족시키기 위해서단일테이블로 간단한데이 터베이스를구축할수있다.하지만,대부분의문제는몇개의테이블과서로다 른 테이블간에 행이 연결된 관계를 요구한다. 테이블 사이 연결을 만들 때, 좀더 사려깊은설계와데이터베이스의역량을 가장 잘사용할수있는데이터베이스 정규화규칙을따르는 것이중요하다.데이터베이스를사용하는주요동기는처 리할 데이터의 양이 많기 때문에, 데이터를 효과적으로 모델링해서 프로그램이 가능하면빠르게실행되게만드는 것이중요하다. 제 12절 디버깅 SQLite 데이터베이스에 연결하는 파이썬 프로그램을 개발할 때 하나의 일반적 인패턴은파이썬프로그램을실행하고 SQLite데이터베이스브라우저를통해 서 결과를 확인하는 것이다. 브라우저를 통해서 빠르게 프로그램이 정상적으로 작동하는지를확인할수있다. SQLite에서두프로그램이동시에동일한데이터를변경하지못하기때문에주 의가필요하다.예를들어,브라우저에서데이터베이스를열고데이터베이스에 변경을 하고 저장(save) 버튼을 누르지 않는다면, 브라우져는 데이터베이스 파일에 락(lock) 을 걸구,다른프로그램이파일에접근하는 것을막는다.특 히,파일이 잠겨져 있으면 작성하고 있는파이썬프로그램이파일에접근할수 없다. 해결책은데이터베이스가 잠겨져 있어서파이썬코드가 작동하지않는문제를 피하도록 파이썬에서 데이터베이스에 접근하려 시도하기 전에 데이터베이스 브라우져를닫거나혹은 File메뉴를사용해서브라우져데이터베이스를닫는 것이다.
206 188 제 14 장. 데이터베이스와 SQL(Structured Query Language)사용하기 제 13절 용어정의 속성(attribute): 튜플내부에 값의하나.좀더 일반적으로 열, 칼럼, 필드 로불린다. 제약(constraint): 데이터베이스가 테이블의 필드나 행에 규칙을 강제하는 것. 일반적인제약은특정필드에중복된 값이없도록하는 것(즉,모든 값이 유일해야한다.) 커서(cursor): 커서를 사용해서 데이터베이스에서 SQL 명령어를 수행하고 데 이터베이스에서데이터를 가져온다. 커서는네트워크연결을 위한소켓 이나파일의파일핸들러와 유사하다. 데이터베이스 브라우져(database browser): 프로그램을 작성하지 않고 직접 적으로데이터베이스에연결하거나데이터베이스를조작할수있는소 프트웨어. 외부키(foreign key): 다른테이블에 있는행의주키를 가리키는숫자키.외부 키는다른테이블에저장된행사이에관계를설정한다. 인텍스(index): 테이블에 행이 추가될 때 정보 검색하는 것을 빠르게 하기 위해 서 데이터베이스 소프트웨어가 유지관리하는 추가 데이터. 논리키(logical key): 외부세계 가특정행의정보를찾기 위해서사용하는 키.사용자 계정테이블의예로,사람의전자우편주소는사용자데이터에 대한논리키의좋은후보자가될수있다. 정규화(normalization): 어떠한 데이터도 중복이 없도록 데이터 모델을 설계하 는 것.데이터베이스한장소에데이터 각항목정보를저장하고외부키를 이용하여다른 곳에서참조한다. 주키(primary key): 다른 테이블에서 테이블의 한 행을 참조하기 위해서 각 행 에대입되는숫자키.종종데이터베이스는행이삽입될때주키를 자동 삽입하도록 설정되었다. 관계(relation): 튜플과속성을담고 있는데이터베이스내부영역.좀더 일반적 으로 테이블(table) 이라고한다. 튜플(tuple): 데이터베이스테이블에단일항목으로속성집합이다.좀더 일반 적으로 행(row) 이라고한다.
207 제 15 장 데이터 시각화 지금까지파이썬언어 자체를학습했고,데이터를다루기 위해서파이썬,네트 워크,그리고데이터베이스를어떻게활용하는가도학습했다. 이번장에서는학습한모두를모아완전한 응용프로그램세개를 작성하여데 이터관리와시각화할것이다.실제문제를해결하는데시작할수있는샘플 코드로도 응용프로그램을 사용할 수도 있다. 각 응용프로그램은 ZIP파일로압축되어서다운로드받아로컬 컴퓨터에압축 을풀고실행한다. 제 1절 지리정보데이터로구글맵생성하기 이번 프로젝트에서 구글 지오코딩(geocoding) API를 사용해서 사용자가 입력 한대학교 이름지리정보를정리하고구글지도에데이터를표시한다. 시작하기 위해서 다음 url에서 응용프로그램을 다운로드 한다.
208 190 제 15 장. 데이터 시각화 해결할첫번째문제는무료구글지오코딩 API가 일일요청횟수에제한이 있다 는 것이다.그래서,만약데이터가많다면,여러번중지, 재시작하는 검색프로 세스가요구된다.그래서,문제를두단계로나누었다. 첫번째 단계에서, where.data 파일에 설문(survey) 데이터를 받는다. 한번에 한줄씩 읽고 구글에서 지리정보를 자져와 geodata.sqlite 데이터베이스에 저장 한다. 각사용자가 입력한 위치에대한지오코딩 API를사용하기전에,특정 입력 라인에 데이터가 있는지를 확인하기 위해서 간단히 점검한다. 데이터베이 스는지오코딩데이터의로컬 캐쉬(cache) 처럼동작해서두번동일데이터에 대해서는구글에요청하지않도록한다. geodata.sqlite 파일을 제거함으로써 언제라도 프로세스를 재시작할 수 있다. geoload.py 프로그램을 실행한다. geoload.py 프로그램은 where.data에 입력 라 인을 읽고, 각라인별로데이터베이스존재유무를확인한다.만약 위치에대한 데이터가없다면,지오코딩 API를호출해서데이터를 가져오고데이터베이스 에저장한다. 약간의 데이터가 데이터베이스에 이미 존재한 것을 확인한 후에 샘플로 실행한 결과가다음에 있다. Found in database Northeastern University Found in database University of Hong Kong,... Found in database Technion Found in database Viswakarma Institute, Pune, India Found in database UMD Found in database Tufts University Resolving Monash University Retrieving geocode/json?sensor=false&address=monash+university Retrieved 2063 characters { "results" : [ {u'status': u'ok', u'results':... } Resolving Kokshetau Institute of Economics and Management Retrieving geocode/json?sensor=false&address=kokshetau+inst... Retrieved 1749 characters { "results" : [ {u'status': u'ok', u'results':... }... 첫 다섯 지점은 이미 데이터베이스에 있으므로 건너뛴다. 프로그램은 가져오지 못한 위치 정보를 찾아 스캔하고 정보를 가져온다. geoload.py는언제라도멈춰정지시킬수있다.실행할때마다지오코딩 API 호출횟수를제한하기 위한 카운터가 있다. where.data에수백개의데이터항 목만 있다면,하루사용량한계를넘지않을 것을 것이다.하지만,만약더많은 데이터가 있다면,모든 입력데이터에대한모든지리정보데이터로구성된데 이터베이스를만들기 위해서몇일에 걸쳐서여러번실행할지도모른다. 데이터를 geodata.sqlite에 적재하면, geodump.py 프로그램을 사용하여 데이 터를시각화할수있다.프로그램이데이터베이스를 읽고 위치, 위도, 경도를 실행가능한 자바스크립 코드로 where.js에 쓴다.
209 2. 네트워크와 상호 연결 시각화 191 geodump.py프로그램실행결과는다음과 같다. Northeastern University,... Boston, MA 02115, USA Bradley University, Peoria, IL 61625, USA Technion, Viazman 87, Kesalsaba, 32000, Israel Monash University Clayton... VIC 3800, Australia Kokshetau, Kazakhstan records written to where.js Open where.html to view the data in a browser where.html 파일은 HTML과 자바스크립트로 구성되어서 구글 맵을 시각화 한다. where.js에 가장 최신 데이터를 읽어서 시각화할 데이터로 사용한다. where.js파일형식은다음과 같다. mydata = [ [ , , 'Northeastern Uni... Boston, MA 02115'], [ , , 'Bradley University,... Peoria, IL 61625, USA'], [ , , 'Technion, Viazman 87, Kesalsaba, 32000, Israel'],... ]; 리스트의 리스트를 담고 있는 자바스크립트다. 자바스크립트 리스트 상수에 대 한구문은파이썬과매우 유사하여,구문이여러분에게매우 친숙해야한다. 위치를보기 위해서브라워져에서 where.html을연다. 각맵핀을여기저기돌 아다니면서지오코딩 API가사용자가 입력한 것에대해서반환한 위치를찾는 다. where.html파일을열었을때어떤데이터도볼수없다면, 자바스크립트나 브라우저 개발자콘솔을확인한다. 제 2절 네트워크와상호연결시각화 이번 응용프로그램에서 검색엔진기능 일부를수행한다.먼저웹의 일부분을스 파이더링하고어느페이지가 가장많이연결되었는지 결정하기 위해서 간략한 구글페이지랭크알고리즘을실행한다.스파이더링한 작은웹조각에대해서 연결성과페이지랭크를시각화한다.시각화산출물을만들기 위해서 D3 자바 스크립트 시각화 라이브러리 사용한다. 응용프로그램을다음 url에서다운로드받아압축을푼다.
210 192 제 15 장. 데이터 시각화 첫프로그램(spider.py)은웹사이트를크롤(craw)하고 일련의페이지를뽑아내 서 데이터베이스(spider.sqlite)에 넣어 페이지 간에 링크를 기록한다. 언제라도 spider.sqlite 파일을 제거하고 spider.py를 재실행함으로써 프로세스를 다시 시 작할수있다. Enter web url or enter: [' How many pages: How many pages: 샘플실행결과,웹사이트를크롤해서,웹페이지두개를 가져왔다.프로그램을 재실행해서 좀더 많은 웹페이지를 크롤하게 한다면, 데이터베이스에 이미 등록 된웹페이지는다시크롤하지는않는다. 재시작할때무작위로크롤하지않은 페이지로 이동해서 그곳에서 크롤링을 시작한다. 그래서 연속적으로 spider.py 을실행하는 것은추가적이된다. Enter web url or enter: [' How many pages: How many pages: 같은데이터베이스에서다중시작지점을 가질수있다.프로그램내부에서 이를 webs 라고부른다.스파이더는모든웹사이트에서방문하지않는링크중에 무작위로선택하여방문할다음웹페이지를선정한다. spider.sqlite 파일에 들어있는 내용을 살펴보고자 한다면, 다음과 같이 spdump.py을실행한다. (5, None, 1.0, 3, u' (3, None, 1.0, 4, u' (1, None, 1.0, 2, u' (1, None, 1.0, 5, u' 4 rows.
211 2. 네트워크와 상호 연결 시각화 193 인입링크수, 이전페이지랭크,신규페이지랭크,페이지 id,페이지 url을보 여준다. spdump.py프로그램은최소한하나의 인입링크가 있는페이지만을 보여준다. 데이터베이스에 몇개의 페이지가 있다면, sprank.py 프로그램을 실행하여 페이 지에대한페이지랭크를실행한다.단순하게얼마나많이페이지랭크반복을 수행할지 지정한다. How many iterations: [(1, 0.559), (2, 0.659), (3, 0.985), (4, 2.135), (5, 0.659)] 데이터베이스를 다시 열어서 페이지 랭크가 갱신되었는지 확인한다. (5, 1.0, 0.985, 3, u' (3, 1.0, 2.135, 4, u' (1, 1.0, 0.659, 2, u' (1, 1.0, 0.659, 5, u' 4 rows. sprank.py를원하는만큼실행한다.실행할때마다페이지랭크를정교화한다. sprank.py을 몇번 실행하고 나서 spider.py으로 좀더 많은 페이지를 스파이더 링한다.그리고나서, sprank.py을실행하여페이지랭크 값을다시수렴하여 갱신한다. 검색엔진은 일반적으로동시에크롤링과랭킹프로그램을실행한다. 웹페이지를 다시 스파이더링하지 않고, 페이지 랭크 계산을 재시작하고자 한다 면, spreset.py을사용하고나서 sprank.py를다시시작한다. How many iterations: e e e e e e e e-05 [(512, ), (1, 12.79), (2, 28.93), (3, 6.808), (4, 13.46)] 페이지랭크알고리즘을매번반복하면,페이지마다페이지랭크평균변화를 출력한다.초기에네트워크는매우불균형상태여서 각각의페이지랭크 값은 반복할때마다요동친다.하지만,짧게몇번반복한다음에페이지랭크는수 렴한다. prank.py을충분히오랜동안실행해서페이지랭크 값을수렴하게만 든다.
212 194 제 15 장. 데이터 시각화 페이지랭크에대해서현재최상위페이지를시각화하고자한다면, spjson.py 을실행하여데이터베이스를 읽고웹브라우져에서볼수있는 JSON형식으로 가장 많이 연결된 페이지에 대해서 데이터를 저장한다. Creating JSON output on spider.json... How many nodes? 30 Open force.html in a browser to view the visualization 웹브라우져에 force.html파일을열어 작업데이터 결과를볼수있다.노드와 링크의 자동레이아웃을보여준다. 임의노드를클릭하고끌수도 있고,노드를 더블클릭해서노드로표현된 URL을확인할수있다. 만약다른 유틸리티를 재실행하고자하면, spjson.py을다시실행하고브라우 져의 새로 고치기를 눌러서 spider.json에서 새로운 데이터를 가져온다. 제 3절 전자우편데이터시각화 책을 이 지점까지 읽어오면서 mbox-short.txt과 mbox.txt 파일에 매우 친숙해 졌을 것이다. 이제는전자우편데이터분석수준을다음단계로옮겨갈때다. 실무에서종종서버에서전자우편데이터를 가져오는 것은시간이많이 걸리고, 가져온데이터는오류가많고, 일관되지못하고,많은보정과정비가필요하다. 이번 장에서,지금까지 작성한 가장복잡한 응용프로그램을 가지고 거의 1GB 데이터를 추출하여 시각화 작업을 한다. 응용프로그램을다음 url에서다운로드한다. 무료 전자우편 보관 서비스 데이터를 사용한다. 전자우편 활동에대한멋진보관서비스를 검색기능과함께제공하기때문에,오픈소스 프로젝트에서는매우 인기가높다. API를통한데이터접근에대해서도매우
213 3. 전자우편 데이터 시각화 195 자유로운정책을 유지한다.사용량에대한제한은없지만, 자율적으로서비스 에부하를너무많이주지말고필요한데이터만 가져가도록요청한다. gmane 의 사용조건에 대해서는 다음 페이지를 참조한다. 서비스접근에지연을추가하거나오랜기간에 걸쳐서 장시간이소요되는 작업 을분산함으로써 gmane.org데이터를책임감있게사용하는 것은매우중요하 다.다른사용자를 위해서무료서비스를오용하지말고,서비스를망치지말아 주세요. 이프로그램을사용하여 Sakai전자우편주소데이터를스파이더링하면, 거의 1 GB의데이터를생성하고몇일에 걸쳐서수차례실행을해야한다. ZIP압축 파일내부에 README.txt이어떻게대부분의 Sakai전자우편코퍼스(corpus) 를다운로드할수있는지에대한안내정보를담고 있다.그래서단지프로그램 을 실행하기 위해서 5일 동안 스파이더링을 할 필요는 없다. 이미 스파이더링된 콘텐츠를다운로드했다면,좀더최근의메시지를 가져오기 위해서스파이더링 프로세스를다시실행해야한다. 첫단계는 gmane저장소를스파이더링하는 것이다.기본 URL은 gmane.py파 일과 Sakai 개발자리스트에하드코딩되어 있다.기본 url을변경함으로써또 다른 저장소를 스파이더링 할 수 있다. 기본 url을 변경하는 경우 content.sqlite 파일을필히삭제하세요. gmane.py 파일은 책임감있는 캐쉬 스파이더로서 작동한다. 천천히 실행되며 1 초에한개의전자우편메시지를 가져와서 gmane에 의해서 작동못하게되는 것을피한다.데이터베이스모든데이터를저장한다.필요하면 자주중단하고 재시작한다.모든데이터를 가져오는데몇시간이 걸릴수있다.그래서여러번 재시작하는 것이필요하다. Sakai 개발자리스트에 있는마지막 5개메시지를 가져오는프로그램 gmane.py 을실행한 결과다. How many messages: nealcaidin@sakaifoundation.org re: [building samuelgutierrezjimenez@gmail.com re: [building da1@vt.edu [building sakai] melete 2.9 oracle m.shedid@elraed-it.com [building sakai] samuelgutierrezjimenez@gmail.com re: Does not start with From 프로그램은 1번 부터 이미 스파이더링되지 않는 첫 메시지까지 content.sqlite을 스캔하고 그 메시지에서 스파이더링을 시작한다. 원하는 메시지 숫자를 스파이 더링할때까지 계속하거나 잘못된형식의메시지가나오는페이지에도달할 때까지스파이더링을 계속한다.
214 196 제 15 장. 데이터 시각화 때때로 gmane.org도 메시지를 잃어버린다. 아마도 관리자가 메시지를 삭제 하거나아마도분실했을 것이다.만약스파이더가멈추고 잃어버린메시지를만 나게되면 SQLite매니저로 가서다른모든행을 공백으로구성하고 잃어버린 id를 가진행을추가하여 gmane.py을 재시작한다. 이렇게함으로써스파이더링 프로세스를 재시작하고 계속진행할수있다.빈메시지는다음번프로세스에 서는 무시된다. 모든메시지를스파이더링하고 content.sqlite파일에넣게되면,리스트에메시 지가 보내질 때 gmane.py을 다시 시작해서 새로운 메시지를 얻게 된다. content.sqlite 데이터는 원데이터 형식이고 비효율적인 데이터 모델을 가지고 있으며압축되어 있지않다. 의도적으로그렇게함으로써 SQLite매니저가 content.sqlite파일을직접살펴보고,스파이더링프로세스에서문제를디버그할수 있도록한다.매우느린상태에서데이터베이스에질의를실행하는 것은좋은 생각은아니다. 두번째 프로세스는 gmodel.py 프로그램을 실행하는 것이다. content.sqlite로부 터 가다듬지않은원데이터를 읽어서 index.sqlite파일에깨끗하게 잘모델링된 형식 데이터로 저장한다. index.sqlite 파일은 content.sqlite 보다 10배이상 크기 가 적다. 왜냐하면 헤더와 본문 텍스트를 압축하기 때문이다. gmodel.py을 실행할 때마다, index.sqlite를 삭제하고 다시 생성한다. 그래서 함으로써데이터정비프로세스를약간바꾸는데매개변수를조정하고 content.sqlite의매핑테이블을편집할수있게한다.다음은 gmodel.py을샘플로 실행시킨 것이다.매번 250개전자우편메시지가처리될때마다한라인을출력 해서 거의 1GB전자우편데이터를처리하는동안진행사항을지켜볼수있다. Loaded allsenders 1588 and mapping 28 dns mapping T23:34:30-06:00 ggolden22@mac.com T10:03:20-08:00 tpamsler@ucdavis.edu T11:17:34-05:00 lance@indiana.edu T11:13:28-08:00 vrajgopalan@ucmerced.edu... gmodel.py프로그램은많은데이터정비 작업을처리한다. 도메인 이름이.com,.org,.edu,.net에대해서는 2단계로다른도메인 이름은 3 단계로 잘랐다. 그래서 si.umich.edu은 umich.edu이 되고, caret.cam.ac.uk 은 cam.ac.uk이된다.또한전자우편주소는소문자가되게하고,다음과 있는실제전자우편주소와매칭하 여실제주소로변환한다. arwhyte-63axycvo3tyhxe+lvdladg@public.gmane.org content.sqlite 데이터베이스를 살펴보면, 도메인 이름과 전자우편 주소가 시간 에따라변경되는 것을보정하려고 개인전자우편주소를매핑하는테이블이 두개 있다.예를들어, Sakai 개발자리스트 개발기간에 걸쳐직업을바꿈에따 라 Steve Githens는 다음 전자우편 주소를 사용했다. s-githens@northwestern.edu sgithens@cam.ac.uk swgithen@mtu.edu
215 3. 전자우편 데이터 시각화 197 content.sqlite의 매핑(Mapping) 테이블에 항목을 두개를 추가해서 gmodel.py 프로그램이 3개주소를하나로매핑한다. -> -> 다중 DNS 이름을하나의 DNS 이름으로매핑하려면 DNSMapping테이블에 비슷한항목을생성할수있다.다음매핑이 Sakai데이터에추가된다. iupui.edu -> indiana.edu 그래서, 다양한 인디애나 대학교 캠퍼스의 모든 계정이 함께 추적된다. 데이터를볼때마다, gmodel.py를반복적으로실행하고데이터를좀더깨끗하 게만들기 위해서매핑을추가한다. 작업이마쳐지면, index.sqlite에 인덱스 잘 된버젼의전자우편데이터가 있다. 자료분석을 위해 이파일을사용한다. 이 파일로데이터분석은정말빠르게수행된다. 첫번째, 가장 간단한 자료분석은 누가 가장많은전자우편을보냈는가? 와 어느조직에서 가장많은전자우편을보냈는가? 를알아보는 것이다. gbasic.py 을사용해서수행할수있다. How many to dump? 5 Loaded messages= subjects= senders= 1584 Top 5 list participants steve.swinsburg@gmail.com 2657 azeckoski@unicon.net 1742 ieb@tfd.co.uk 1591 csev@umich.edu 1304 david.horwitz@uct.ac.za 1184 Top 5 list organizations gmail.com 7339 umich.edu 6243 uct.ac.za 2451 indiana.edu 2258 unicon.net 2055 gmane.py이나 혹은 gmodel.py과 비교하여 gbasic.py이 얼마나 빨리 실행되는 지주목하세요.모두동일한데이터에서 작업을수행하지만, gbasic.py은 index.sqlite에 저장된 압축되고 정규화된 데이터를 사용한다. 처리할 데이터가 많다면, 응용프로그램과 같이다중-단계프로세스를 개발하는데시간이약간 더 걸리지만, 데이터를 탐색하고 시각화할 때는 많은 시간을 절약해 준다. gword.py파일에주제라인의단어빈도를 간략히시각화할수있다. Range of counts: Output written to gword.js 이번 장처음의 것과 유사한워드클라우드를생성하기 위해서 gword.htm를 사용하여시각화할 gword.js파일을생성한다.
216 198 제 15 장. 데이터 시각화 두번째시각화는 gline.py으로생성된다.시간에따른조직별전자우편참여를 연산한다. Loaded messages= subjects= senders= 1584 Top 10 Oranizations ['gmail.com', 'umich.edu', 'uct.ac.za', 'indiana.edu', 'unicon.net', 'tfd.co.uk', 'berkeley.edu', 'longsight.com', 'stanford.edu', 'ox.ac.uk'] Output written to gline.js 출력값은 gline.htm을 사용하여 시각화된 gline.js에 쓰여진다. 작성한프로그램은상대적으로복잡하고정교한 응용프로그램으로실제데이 터를불러오고,정비하고,시각화하는기능을 갖고 있다.
Microsoft PowerPoint - chap02-C프로그램시작하기.pptx
#include int main(void) { int num; printf( Please enter an integer "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); return 0; } 1 학습목표 을 작성하면서 C 프로그램의
More information정보교육을위한파이썬 정보탐색 Version d2 저자 : Charles Severance 번역 : 이광춘, 한정수 (xwmooc)
정보교육을위한파이썬 정보탐색 Version 0.0.9-d2 저자 : Charles Severance 번역 : 이광춘, 한정수 (xwmooc) Copyright 2009- Charles Severance. Printing history: October 2013: Major revision to Chapters 13 and 14 to switch to JSON
More informationChapter 2 변수와 수식 그리고 문장 프로그래밍 언어의 가장 강력한 기능 중 하나는 변수(variable)가 조작 가능하다는 것이다. 변수 는 값에 부여하는 이름이다. 2.1 할당문 할당문(assignment statement)은 새로운 변수를 생성하고 값을 부여
Chapter 2 변수와 수식 그리고 문장 프로그래밍 언어의 가장 강력한 기능 중 하나는 변수(variable)가 조작 가능하다는 것이다. 변수 는 값에 부여하는 이름이다. 2.1 할당문 할당문(assignment statement)은 새로운 변수를 생성하고 값을 부여한다. >>> message = 'And now for something completely
More informationMicrosoft PowerPoint - chap01-C언어개요.pptx
#include int main(void) { int num; printf( Please enter an integer: "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); return 0; } 1 학습목표 프로그래밍의 기본 개념을
More informationOCW_C언어 기초
초보프로그래머를위한 C 언어기초 4 장 : 연산자 2012 년 이은주 학습목표 수식의개념과연산자및피연산자에대한학습 C 의알아보기 연산자의우선순위와결합방향에대하여알아보기 2 목차 연산자의기본개념 수식 연산자와피연산자 산술연산자 / 증감연산자 관계연산자 / 논리연산자 비트연산자 / 대입연산자연산자의우선순위와결합방향 조건연산자 / 형변환연산자 연산자의우선순위 연산자의결합방향
More informationMicrosoft PowerPoint - chap04-연산자.pptx
int num; printf( Please enter an integer: "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); } 1 학습목표 수식의 개념과 연산자, 피연산자에 대해서 알아본다. C의 를 알아본다. 연산자의 우선 순위와 결합 방향에
More informationChapter 5 조건문과 재귀문 프로그램의 상태에 따라 다른 코드를 실행하는 if문이 이 장의 핵심 주제이다. 그 전에 내림 나눗 셈 연산자와 나머지 연산자를 살펴보자. 5.1 내림 나눗셈과 나머지 연산자 내림 나눗셈 연산자 //는 두 수를 나누어 얻은 결과 값의 정
Chapter 5 조건문과 재귀문 프로그램의 상태에 따라 다른 코드를 실행하는 if문이 이 장의 핵심 주제이다. 그 전에 내림 나눗 셈 연산자와 나머지 연산자를 살펴보자. 5.1 내림 나눗셈과 나머지 연산자 내림 나눗셈 연산자 //는 두 수를 나누어 얻은 결과 값의 정수 값을 취한다. 예를 들어, 105분 길이의 영화가 있다고 했을 때 몇 시간 짜리 영화인지
More informationMicrosoft PowerPoint - chap05-제어문.pptx
int num; printf( Please enter an integer: "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); 1 학습목표 제어문인,, 분기문에 대해 알아본다. 인 if와 switch의 사용 방법과 사용시 주의사항에 대해 알아본다.
More information다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");
다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp"); dispatcher.forward(request, response); - 위의예에서와같이 RequestDispatcher
More informationuntitled
시스템소프트웨어 : 운영체제, 컴파일러, 어셈블러, 링커, 로더, 프로그래밍도구등 소프트웨어 응용소프트웨어 : 워드프로세서, 스프레드쉬트, 그래픽프로그램, 미디어재생기등 1 n ( x + x +... + ) 1 2 x n 00001111 10111111 01000101 11111000 00001111 10111111 01001101 11111000
More information<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>
리눅스 오류처리하기 2007. 11. 28 안효창 라이브러리함수의오류번호얻기 errno 변수기능오류번호를저장한다. 기본형 extern int errno; 헤더파일 라이브러리함수호출에실패했을때함수예 정수값을반환하는함수 -1 반환 open 함수 포인터를반환하는함수 NULL 반환 fopen 함수 2 유닉스 / 리눅스 라이브러리함수의오류번호얻기 19-1
More informationMicrosoft PowerPoint - 3ÀÏ°_º¯¼ö¿Í »ó¼ö.ppt
변수와상수 1 변수란무엇인가? 변수 : 정보 (data) 를저장하는컴퓨터내의특정위치 ( 임시저장공간 ) 메모리, register 메모리주소 101 번지 102 번지 변수의크기에따라 주로 byte 단위 메모리 2 기본적인변수형및변수의크기 변수의크기 해당컴퓨터에서는항상일정 컴퓨터마다다를수있음 short
More information10 강. 쉘스크립트 l 쉘스크립트 Ÿ 쉘은명령어들을연속적으로실행하는인터프리터환경을제공 Ÿ 쉘스크립트는제어문과변수선언등이가능하며프로그래밍언어와유사 Ÿ 프로그래밍언어와스크립트언어 -프로그래밍언어를사용하는경우소스코드를컴파일하여실행가능한파일로만들어야함 -일반적으로실행파일은다
10 강. 쉘스크립트 쉘스크립트 쉘은명령어들을연속적으로실행하는인터프리터환경을제공 쉘스크립트는제어문과변수선언등이가능하며프로그래밍언어와유사 프로그래밍언어와스크립트언어 -프로그래밍언어를사용하는경우소스코드를컴파일하여실행가능한파일로만들어야함 -일반적으로실행파일은다른운영체제로이식되지않음 -스크립트언어를사용하면컴파일과정이없고인터프리터가소스파일에서명령문을판독하여각각의명령을수행
More informationMulti-pass Sieve를 이용한 한국어 상호참조해결 반-자동 태깅 도구
Python: 파이썬이란무엇인가? Kangwon Natl. University Department of Computer Science Cheoneum Park Intelligent software Lab. 파이썬이란? Python 1990년암스테르담의귀도반로섬 (Guido Van Rossum) 이개발한인터프리터언어 국내외에서교육, 실무등에서많이사용 구글의소프트웨어,
More informationPowerPoint 프레젠테이션
Chapter 06 반복문 01 반복문의필요성 02 for문 03 while문 04 do~while문 05 기타제어문 반복문의의미와필요성을이해한다. 대표적인반복문인 for 문, while 문, do~while 문의작성법을 알아본다. 1.1 반복문의필요성 반복문 동일한내용을반복하거나일정한규칙으로반복하는일을수행할때사용 프로그램을좀더간결하고실제적으로작성할수있음.
More information슬라이드 1
Pairwise Tool & Pairwise Test NuSRS 200511305 김성규 200511306 김성훈 200614164 김효석 200611124 유성배 200518036 곡진화 2 PICT Pairwise Tool - PICT Microsoft 의 Command-line 기반의 Free Software www.pairwise.org 에서다운로드후설치
More informationMicrosoft PowerPoint - chap-03.pptx
쉽게풀어쓴 C 언어 Express 제 3 장 C 프로그램구성요소 컴퓨터프로그래밍기초 이번장에서학습할내용 * 주석 * 변수, 상수 * 함수 * 문장 * 출력함수 printf() * 입력함수 scanf() * 산술연산 * 대입연산 이번장에서는 C프로그램을이루는구성요소들을살펴봅니다. 컴퓨터프로그래밍기초 2 일반적인프로그램의형태 데이터를받아서 ( 입력단계 ), 데이터를처리한후에
More informationInfinity(∞) Strategy
반복제어 표월성 passwd74@cherub.sungkyul.edu 개요 for() 문 break문과 continue문 while문 do-while문 for() 문 for() 문형식 for( 표현식1; 표현식2; 표현식3) 여러문장들 ; 표현식 1 : 초기화 (1 번만수행 ) 표현식 2 : 반복문수행조건 ( 없으면무한반복 ) 표현식 3 : 반복문수행횟수 for()
More information4. #include <stdio.h> #include <stdlib.h> int main() { functiona(); } void functiona() { printf("hihi\n"); } warning: conflicting types for functiona
이름 : 학번 : A. True or False: 각각항목마다 True 인지 False 인지적으세요. 1. (Python:) randint 함수를사용하려면, random 모듈을 import 해야한다. 2. (Python:) '' (single quote) 는한글자를표현할때, (double quote) 는문자열을표현할때사용한다. B. 다음에러를수정하는방법을적으세요.
More informationPowerPoint 프레젠테이션
Lecture 02 프로그램구조및문법 Kwang-Man Ko kkmam@sangji.ac.kr, compiler.sangji.ac.kr Department of Computer Engineering Sang Ji University 2018 자바프로그램기본구조 Hello 프로그램구조 sec01/hello.java 2/40 자바프로그램기본구조 Hello 프로그램구조
More informationMicrosoft PowerPoint - chap03-변수와데이터형.pptx
#include int main(void) { int num; printf( Please enter an integer: "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num %d\n", num); return 0; } 1 학습목표 의 개념에 대해 알아본다.
More information금오공대 컴퓨터공학전공 강의자료
C 프로그래밍프로젝트 Chap 14. 포인터와함수에대한이해 2013.10.09. 오병우 컴퓨터공학과 14-1 함수의인자로배열전달 기본적인인자의전달방식 값의복사에의한전달 val 10 a 10 11 Department of Computer Engineering 2 14-1 함수의인자로배열전달 배열의함수인자전달방식 배열이름 ( 배열주소, 포인터 ) 에의한전달 #include
More information비트와바이트 비트와바이트 비트 (Bit) : 2진수값하나 (0 또는 1) 를저장할수있는최소메모리공간 1비트 2비트 3비트... n비트 2^1 = 2개 2^2 = 4개 2^3 = 8개... 2^n 개 1 바이트는 8 비트 2 2
비트연산자 1 1 비트와바이트 비트와바이트 비트 (Bit) : 2진수값하나 (0 또는 1) 를저장할수있는최소메모리공간 1비트 2비트 3비트... n비트 2^1 = 2개 2^2 = 4개 2^3 = 8개... 2^n 개 1 바이트는 8 비트 2 2 진수법! 2, 10, 16, 8! 2 : 0~1 ( )! 10 : 0~9 ( )! 16 : 0~9, 9 a, b,
More informationMicrosoft PowerPoint - chap06-2pointer.ppt
2010-1 학기프로그래밍입문 (1) chapter 06-2 참고자료 포인터 박종혁 Tel: 970-6702 Email: jhpark1@snut.ac.kr 한빛미디어 출처 : 뇌를자극하는 C프로그래밍, 한빛미디어 -1- 포인터의정의와사용 변수를선언하는것은메모리에기억공간을할당하는것이며할당된이후에는변수명으로그기억공간을사용한다. 할당된기억공간을사용하는방법에는변수명외에메모리의실제주소값을사용하는것이다.
More informationMicrosoft PowerPoint - Lesson2.pptx
Computer Engineering g Programming g 2 제 3 장 C 프로그래밍구성요소 Lecturer: JUNBEOM YOO jbyoo@konkuk.ac.kr 본강의자료는생능출판사의 PPT 강의자료 를기반으로제작되었습니다. 이번장에서학습할내용 * 주석 * 변수, 상수 * 함수 * 문장 * 출력함수 printf() * 입력함수 scanf() *
More informationMicrosoft PowerPoint - CSharp-10-예외처리
10 장. 예외처리 예외처리개념 예외처리구문 사용자정의예외클래스와예외전파 순천향대학교컴퓨터학부이상정 1 예외처리개념 순천향대학교컴퓨터학부이상정 2 예외처리 오류 컴파일타임오류 (Compile-Time Error) 구문오류이기때문에컴파일러의구문오류메시지에의해쉽게교정 런타임오류 (Run-Time Error) 디버깅의절차를거치지않으면잡기어려운심각한오류 시스템에심각한문제를줄수도있다.
More informationPowerPoint 프레젠테이션
실습 1 배효철 th1g@nate.com 1 목차 조건문 반복문 System.out 구구단 모양만들기 Up & Down 2 조건문 조건문의종류 If, switch If 문 조건식결과따라중괄호 { 블록을실행할지여부결정할때사용 조건식 true 또는 false값을산출할수있는연산식 boolean 변수 조건식이 true이면블록실행하고 false 이면블록실행하지않음 3
More informationMicrosoft PowerPoint - chap-05.pptx
쉽게풀어쓴 C 언어 Express 제 5 장수식과연산자 컴퓨터프로그래밍기초 이번장에서학습할내용 * 수식과연산자란? * 대입연산 * 산술연산 * 논리연산 * 관계연산 * 우선순위와결합법칙 이번장에서는수식과연산자를살벼봅니다. 컴퓨터프로그래밍기초 2 수식 수식 (expression) x + y x*x + 5*x + 6 (principal * interest_rate
More information<B3EDB9AEC0DBBCBAB9FD2E687770>
(1) 주제 의식의 원칙 논문은 주제 의식이 잘 드러나야 한다. 주제 의식은 논문을 쓰는 사람의 의도나 글의 목적 과 밀접한 관련이 있다. (2) 협력의 원칙 독자는 필자를 이해하려고 마음먹은 사람이다. 따라서 필자는 독자가 이해할 수 있는 말이 나 표현을 사용하여 독자의 노력에 협력해야 한다는 것이다. (3) 논리적 엄격성의 원칙 감정이나 독단적인 선언이
More information프로그래밍개론및실습 2015 년 2 학기프로그래밍개론및실습과목으로본내용은강의교재인생능출판사, 두근두근 C 언어수업, 천인국지음을발췌수정하였음
프로그래밍개론및실습 2015 년 2 학기프로그래밍개론및실습과목으로본내용은강의교재인생능출판사, 두근두근 C 언어수업, 천인국지음을발췌수정하였음 CHAPTER 9 둘중하나선택하기 관계연산자 두개의피연산자를비교하는연산자 결과값은참 (1) 아니면거짓 (0) x == y x 와 y 의값이같은지비교한다. 관계연산자 연산자 의미 x == y x와 y가같은가? x!= y
More information쉽게 풀어쓴 C 프로그래밍
두근두근 파이썬수업 4 장자료의종류에는어떤것들이있나요? 이번장에서만들프로그램 (1) 터틀그래픽의거북이와인사하는프로그램을작성해보자. Run Python (2) 여러개의색상을리스트에저장하였다가하나씩꺼내서원들을그려보자 Run Python 파이썬에서사용할수있는자료의종류 파이썬과자료형 변수에어떤종류의자료도저장할수있다 x = 10 print("x =", x) x = 3.14
More informationMicrosoft PowerPoint - e pptx
Import/Export Data Using VBA Objectives Referencing Excel Cells in VBA Importing Data from Excel to VBA Using VBA to Modify Contents of Cells 새서브프로시저작성하기 프로시저실행하고결과확인하기 VBA 코드이해하기 Referencing Excel Cells
More informationPowerPoint Presentation
객체지향프로그래밍 클래스, 객체, 메소드 ( 실습 ) 손시운 ssw5176@kangwon.ac.kr 예제 1. 필드만있는클래스 텔레비젼 2 예제 1. 필드만있는클래스 3 예제 2. 여러개의객체생성하기 4 5 예제 3. 메소드가추가된클래스 public class Television { int channel; // 채널번호 int volume; // 볼륨 boolean
More information윈도우즈프로그래밍(1)
제어문 (2) For~Next 문 윈도우즈프로그래밍 (1) ( 신흥대학교컴퓨터정보계열 ) 2/17 Contents 학습목표 프로그램에서주어진특정문장을부분을일정횟수만큼반복해서실행하는문장으로 For~Next 문등의구조를이해하고활용할수있다. 내용 For~Next 문 다중 For 문 3/17 제어문 - FOR 문 반복문 : 프로그램에서주어진특정문장들을일정한횟수만큼반복해서실행하는문장
More information152*220
152*220 2011.2.16 5:53 PM ` 3 여는 글 교육주체들을 위한 교육 교양지 신경림 잠시 휴간했던 우리교육 을 비록 계간으로이지만 다시 내게 되었다는 소식을 들으니 우 선 반갑다. 하지만 월간으로 계속할 수 없다는 현실이 못내 아쉽다. 솔직히 나는 우리교 육 의 부지런한 독자는 못 되었다. 하지만 비록 어깨너머로 읽으면서도 이런 잡지는 우 리
More information<4D F736F F F696E74202D20C1A633C0E52043C7C1B7CEB1D7B7A5B1B8BCBABFE4BCD2>
쉽게풀어쓴 C 언어 Express 제 3 장 C 프로그램구성요소 이번장에서학습할내용 * 주석 * 변수, 상수 * 함수 * 문장 * 출력함수 printf() * 입력함수 scanf() * 산술연산 * 대입연산 이번장에서는 C 프로그램을이루는구성요소들을살펴봅니다. 일반적인프로그램의형태 데이터를받아서 ( 입력단계 ), 데이터를처리한후에 ( 처리단계 ), 결과를화면에출력
More information<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>
연습문제해답 5 4 3 2 1 0 함수의반환값 =15 5 4 3 2 1 0 함수의반환값 =95 10 7 4 1-2 함수의반환값 =3 1 2 3 4 5 연습문제해답 1. C 언어에서의배열에대하여다음중맞는것은? (1) 3차원이상의배열은불가능하다. (2) 배열의이름은포인터와같은역할을한다. (3) 배열의인덱스는 1에서부터시작한다. (4) 선언한다음, 실행도중에배열의크기를변경하는것이가능하다.
More informationC 프로그램의 기본
C 프로그램의기본 목차 C 프로그램의구성요소 주석 main 함수 출력 C 언어의입력과출력 변수 printf 함수 scanf 함수 2 예제 2-1 : 첫번째 C 프로그램 3 2.1.1 주석 주석의용도 프로그램에대한설명 프로그램전체에대한대략적인정보를제공 프로그램수행에영향을미치지않는요소 4 2.1.1 주석 주석사용방법 /* 과 */ 을이용한여러줄주석 // 을이용한한줄주석
More informationC# Programming Guide - Types
C# Programming Guide - Types 최도경 lifeisforu@wemade.com 이문서는 MSDN 의 Types 를요약하고보충한것입니다. http://msdn.microsoft.com/enus/library/ms173104(v=vs.100).aspx Types, Variables, and Values C# 은 type 에민감한언어이다. 모든
More informationMicrosoft PowerPoint 자바-기본문법(Ch2).pptx
자바기본문법 1. 기본사항 2. 자료형 3. 변수와상수 4. 연산자 1 주석 (Comments) 이해를돕기위한설명문 종류 // /* */ /** */ 활용예 javadoc HelloApplication.java 2 주석 (Comments) /* File name: HelloApplication.java Created by: Jung Created on: March
More informationOCW_C언어 기초
초보프로그래머를위한 C 언어기초 2 장 : C 프로그램시작하기 2012 년 이은주 학습목표 을작성하면서 C 프로그램의구성요소 주석 (comment) 이란무엇인지알아보고, 주석을만드는방법 함수란무엇인지알아보고, C 프로그램에반드시필요한 main 함수 C 프로그램에서출력에사용되는 printf 함수 변수의개념과변수의값을입력받는데사용되는 scanf 함수 2 목차 프로그램코드
More information쉽게
Power Java 제 4 장자바프로그래밍기초 이번장에서학습할내용 자바프로그램에대한기초사항을학습 자세한내용들은추후에. Hello.java 프로그램 주석 주석 (comment): 프로그램에대한설명을적어넣은것 3 가지타입의주석 클래스 클래스 (class): 객체를만드는설계도 ( 추후에학습 ) 자바프로그램은클래스들로구성된다. 그림 4-1. 자바프로그램의구조 클래스정의
More informationMicrosoft PowerPoint - [2009] 02.pptx
원시데이터유형과연산 원시데이터유형과연산 원시데이터유형과연산 숫자데이터유형 - 숫자데이터유형 원시데이터유형과연산 표준입출력함수 - printf 문 가장기본적인출력함수. (stdio.h) 문법 ) printf( Test printf. a = %d \n, a); printf( %d, %f, %c \n, a, b, c); #include #include
More informationC 프로그래밍 언어 입문 C 프로그래밍 언어 입문 김명호저 숭실대학교 출판국 머리말..... C, C++, Java, Fortran, Python, Ruby,.. C. C 1972. 40 C.. C. 1999 C99. C99. C. C. C., kmh ssu.ac.kr.. ,. 2013 12 Contents 1장 프로그래밍 시작 1.1 C 10 1.2 12
More informationMicrosoft PowerPoint 웹 연동 기술.pptx
웹프로그래밍및실습 ( g & Practice) 문양세강원대학교 IT 대학컴퓨터과학전공 URL 분석 (1/2) URL (Uniform Resource Locator) 프로토콜, 호스트, 포트, 경로, 비밀번호, User 등의정보를포함 예. http://kim:3759@www.hostname.com:80/doc/index.html URL 을속성별로분리하고자할경우
More informationPowerPoint Presentation
#include int main(void) { int num; printf( Please enter an integer: "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); return 0; } 1 학습목표 을작성하면서 C 프로그램의구성요소에대하여알아본다.
More informationISP and CodeVisionAVR C Compiler.hwp
USBISP V3.0 & P-AVRISP V1.0 with CodeVisionAVR C Compiler http://www.avrmall.com/ November 12, 2007 Copyright (c) 2003-2008 All Rights Reserved. USBISP V3.0 & P-AVRISP V1.0 with CodeVisionAVR C Compiler
More informationView Licenses and Services (customer)
빠른 빠른 시작: 시작: 라이선스, 라이선스, 서비스 서비스 및 주문 주문 이력 이력 보기 보기 고객 가이드 Microsoft 비즈니스 센터의 라이선스, 서비스 및 혜택 섹션을 통해 라이선스, 온라인 서비스, 구매 기록 (주문 기록)을 볼 수 있습니다. 시작하려면, 비즈니스 센터에 로그인하여 상단 메뉴에서 재고를 선택한 후 내 재고 관리를 선택하십시오. 목차
More information기본소득문답2
응답하라! 기본소득 응답하라! 기본소득 06 Q.01 07 Q.02 08 Q.03 09 Q.04 10 Q.05 11 Q.06 12 Q.07 13 Q.08 14 Q.09 응답하라! 기본소득 contents 16 Q.10 18 Q.11 19 Q.12 20 Q.13 22 Q.14 23 Q.15 24 Q.16 Q.01 기본소득의 개념을 쉽게 설명해주세요. 06 응답하라
More information3장 함수
3 장함수 박창이 서울시립대학교통계학과 박창이 ( 서울시립대학교통계학과 ) 3 장함수 1 / 20 학습내용 함수호출타입변환함수수학함수사용자정의함수파라미터와인자변수와파라미터의범위함수의구분함수를사용하는이유 from을이용한가져오기디버깅변수의범위재귀함수 박창이 ( 서울시립대학교통계학과 ) 3 장함수 2 / 20 함수호출 함수는어떤연산을수행하는일련의명령문들로함수이름으로호출
More informationTEST BANK & SOLUTION
TEST BANK & SOLUTION 어서와자바는처음이지!" 를강의교재로채택해주셔서감사드립니다. 본문제집을만드는데나름대로노력을기울였으나제가가진지식의한계로말미암아잘못된부분이있을것으로사료됩니다. 잘못된부분을발견하시면 chunik@sch.ac.kr로연락주시면더좋은책을만드는데소중하게사용하겠습니다. 다시한번감사드립니다. 1. 자바언어에서지원되는 8 가지의기초자료형은무엇인가?
More information0. 표지에이름과학번을적으시오. (6) 1. 변수 x, y 가 integer type 이라가정하고다음빈칸에 x 와 y 의계산결과값을적으시오. (5) x = (3 + 7) * 6; x = 60 x = (12 + 6) / 2 * 3; x = 27 x = 3 * (8 / 4
Introduction to software design 2012-1 Final 2012.06.13 16:00-18:00 Student ID: Name: - 1 - 0. 표지에이름과학번을적으시오. (6) 1. 변수 x, y 가 integer type 이라가정하고다음빈칸에 x 와 y 의계산결과값을적으시오. (5) x = (3 + 7) * 6; x = 60 x
More information< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>
Chap #2 펌웨어작성을위한 C 언어 I http://www.smartdisplay.co.kr 강의계획 Chap1. 강의계획및디지털논리이론 Chap2. 펌웨어작성을위한 C 언어 I Chap3. 펌웨어작성을위한 C 언어 II Chap4. AT89S52 메모리구조 Chap5. SD-52 보드구성과코드메모리프로그래밍방법 Chap6. 어드레스디코딩 ( 매핑 ) 과어셈블리어코딩방법
More information17장 클래스와 메소드
17 장클래스와메소드 박창이 서울시립대학교통계학과 박창이 ( 서울시립대학교통계학과 ) 17 장클래스와메소드 1 / 18 학습내용 객체지향특징들객체출력 init 메소드 str 메소드연산자재정의타입기반의버전다형성 (polymorphism) 박창이 ( 서울시립대학교통계학과 ) 17 장클래스와메소드 2 / 18 객체지향특징들 객체지향프로그래밍의특징 프로그램은객체와함수정의로구성되며대부분의계산은객체에대한연산으로표현됨객체의정의는
More information학습목차 2.1 다차원배열이란 차원배열의주소와값의참조
- Part2- 제 2 장다차원배열이란무엇인가 학습목차 2.1 다차원배열이란 2. 2 2 차원배열의주소와값의참조 2.1 다차원배열이란 2.1 다차원배열이란 (1/14) 다차원배열 : 2 차원이상의배열을의미 1 차원배열과다차원배열의비교 1 차원배열 int array [12] 행 2 차원배열 int array [4][3] 행 열 3 차원배열 int array [2][2][3]
More informationuntitled
Content Ⅰ. 기본방향 1. 목 적 3 2. 적용범위 3 Ⅱ. 사회복지관 운영 1. 사회복지관의 정의 7 2. 사회복지관의 목표 7 3. 사회복지관의 연혁 7 4. 사회복지관 운영의 기본원칙 8 Ⅲ. 사회복지관 사업 1. 가족복지사업 15 2. 지역사회보호사업 16 3. 지역사회조직사업 18 4. 교육 문화사업 19 5. 자활사업 20 6. 재가복지봉사서비스
More information8장 문자열
8 장문자열 박창이 서울시립대학교통계학과 박창이 ( 서울시립대학교통계학과 ) 8 장문자열 1 / 24 학습내용 문자열 (string) 훑기 (traversal) 부분추출 (slicing) print 함수불변성 (immutablity) 검색 (search) 세기 (count) Method in 연산자비교 박창이 ( 서울시립대학교통계학과 ) 8 장문자열 2 /
More information[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi
2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Function) 1. 함수의개념 입력에대해적절한출력을발생시켜주는것 내가 ( 프로그래머 ) 작성한명령문을연산, 처리, 실행해주는부분 ( 모듈 ) 자체적으로실행되지않으며,
More informationPowerPoint 프레젠테이션
System Software Experiment 1 Lecture 5 - Array Spring 2019 Hwansoo Han (hhan@skku.edu) Advanced Research on Compilers and Systems, ARCS LAB Sungkyunkwan University http://arcs.skku.edu/ 1 배열 (Array) 동일한타입의데이터가여러개저장되어있는저장장소
More informationC++ Programming
C++ Programming 예외처리 Seo, Doo-okok clickseo@gmail.com http://www.clickseo.com 목 차 예외처리 2 예외처리 예외처리 C++ 의예외처리 예외클래스와객체 3 예외처리 예외를처리하지않는프로그램 int main() int a, b; cout > a >> b; cout
More information<4D F736F F F696E74202D20C1A632C0E520C7C1B7CEB1D7B7A5B0B3B9DFB0FAC1A4>
쉽게풀어쓴 C 언어 Express 제 2 장프로그램개발과정 통합개발환경 통합개발환경 (IDE: integrated development environment) 에디터 + 컴파일러 + 디버거 Visual C++: 이클립스 (eclipse): Dev-C++: 마이크로소프트제작 오픈소스프로젝트 오픈소스프로젝트 통합개발환경의종류 비주얼 C++(Visual C++)
More informationMicrosoft PowerPoint - 2주차-1차시 (강의자료) ch01 - C Programming 기초 (part 2)
일반적인프로그램의기본구성형태 데이터를받아서 ( 입력단계 ), 데이터를처리한후에 ( 처리단계 ), 결과를화면에출력 ( 출력단계 ) 한다. 데이터입력 데이터처리 결과출력 1-23 덧셈프로그램 #1 주석 전처리기지시어 /* 두개의숫자의합을계산하는프로그램 */ #include 함수 int main(void) { int x; int y; int sum;
More informationMicrosoft PowerPoint - chap08-1 [호환 모드]
2011-1 학기프로그래밍입문 (1) 참고자료 : chapter 8-1. 전처리 박종혁 Tel: 970-6702 Email: jhpark1@seoultech.ac.kr h k 한빛미디어 출처 : 뇌를자극하는 C프로그래밍, 한빛미디어 -1- ehanbit.net 전처리명령어 컴파일과정에는전처리 (preprocessing) 단계가있다. - 컴파일러는목적파일을만들기전에전처리라고하는특별한작업을
More informationTcl의 문법
월, 01/28/2008-20:50 admin 은 상당히 단순하고, 커맨드의 인자를 스페이스(공백)로 단락을 짓고 나열하는 정도입니다. command arg1 arg2 arg3... 한행에 여러개의 커맨드를 나열할때는, 세미콜론( ; )으로 구분을 짓습니다. command arg1 arg2 arg3... ; command arg1 arg2 arg3... 한행이
More informationMicrosoft PowerPoint - gnu-w09-c-chap
어서와 C 언어는처음이지 제 1 장 컴퓨터 컴퓨터는생각만큼똑똑한물건이아니다. 컴퓨터는스스로자신이수행할작업을결정할수없다. 프로그램 우리가컴퓨터에게아주자세한명령어를주어야한다. 컴퓨터에게특정한작업을수행하게하는자세한명령어의리스트를프로그램 (program) 이라고한다. 1. 정수를읽는다. 2. 합을계산한다. 3. 합을화면에출력한다. 작성해야하는프로그램 일반적인프로그램은구입하거나다운로드받을수있다.
More informationMicrosoft PowerPoint - Perpect C 02.ppt [호환 모드]
02 C 프로그래밍기초 충남대학교이형주 1 C 프로그램구조 콘솔응용프로그램 2 프로그램실행순서 C 프로그램은여러함수의조합으로구성 함수란정해진규칙에의하여일련의작업을수행하는프로그램의단위 실행순서 main 함수는프로그램이실행되면가장먼저시작되는부분 모든함수내부에서는위에서아래로, 좌에서우로, 문장이위치한순서대로실행 3 전처리기 전처리기 (preprocessor) 미리처리하는프로그램으로,
More information아이콘의 정의 본 사용자 설명서에서는 다음 아이콘을 사용합니다. 참고 참고는 발생할 수 있는 상황에 대처하는 방법을 알려 주거나 다른 기능과 함께 작동하는 방법에 대한 요령을 제공합니다. 상표 Brother 로고는 Brother Industries, Ltd.의 등록 상
Android 용 Brother Image Viewer 설명서 버전 0 KOR 아이콘의 정의 본 사용자 설명서에서는 다음 아이콘을 사용합니다. 참고 참고는 발생할 수 있는 상황에 대처하는 방법을 알려 주거나 다른 기능과 함께 작동하는 방법에 대한 요령을 제공합니다. 상표 Brother 로고는 Brother Industries, Ltd.의 등록 상표입니다. Android는
More information문서의 제목 나눔고딕B, 54pt
산업공학과를위한 프로그래밍입문 (w/ 파이썬 ) PART I : 파이썬기초 가천대학교 산업경영공학과 최성철교수 수학연산 Integer 와 Float >>> print 3/2 1 # 왜 1 이나올까? - 파이썬은정수 (Integer) 와소수 (decimal number) 를구분 - 프로그래밍에서소수는부동소수 (floating-point numbers) 또는 float
More information슬라이드 1
-Part3- 제 4 장동적메모리할당과가변인 자 학습목차 4.1 동적메모리할당 4.1 동적메모리할당 4.1 동적메모리할당 배울내용 1 프로세스의메모리공간 2 동적메모리할당의필요성 4.1 동적메모리할당 (1/6) 프로세스의메모리구조 코드영역 : 프로그램실행코드, 함수들이저장되는영역 스택영역 : 매개변수, 지역변수, 중괄호 ( 블록 ) 내부에정의된변수들이저장되는영역
More informationMicrosoft PowerPoint - chap06-1Array.ppt
2010-1 학기프로그래밍입문 (1) chapter 06-1 참고자료 배열 박종혁 Tel: 970-6702 Email: jhpark1@snut.ac.kr 한빛미디어 출처 : 뇌를자극하는 C프로그래밍, 한빛미디어 -1- 배열의선언과사용 같은형태의자료형이많이필요할때배열을사용하면효과적이다. 배열의선언 배열의사용 배열과반복문 배열의초기화 유연성있게배열다루기 한빛미디어
More informationMicrosoft PowerPoint - C프로그래밍-chap03.ppt [호환 모드]
Chapter 03 변수와자료형 2009 한국항공대학교항공우주기계공학부 (http://mercury.kau.ac.kr/sjkwon) 1 변수와자료유형 변수 프로그램에서자료값을임시로기억할수있는저장공간을변수 (variables) 변수 (Variables) 는컴퓨터의메모리인 RAM(Random Access Memory) 에저장 물건을담는박스라고생각한다면박스의크기에따라담을물건이제한됨
More informationKNK_C03_Expr_kor
Expressions adopted from KNK C Programming : A Modern Approach Operators 연산자 C 는표현식을많이사용함 표현식은변수와상수와연산자로구성됨 C 에는연산자의종류가다양함 1. arithmetic operators ( 수식연산자 ) 2. relational operators ( 관계연산자 ) 3. logical
More informationChapter_06
프로그래밍 1 1 Chapter 6. Functions and Program Structure April, 2016 Dept. of software Dankook University http://embedded.dankook.ac.kr/~baeksj 이장의강의목표 2 문자의입력방법을이해한다. 중첩된 if문을이해한다. while 반복문의사용법을익힌다. do 반복문의사용법을익힌다.
More informationPowerPoint 프레젠테이션
Chapter 03 일단짜보는그럴듯한 C 프로그램... 1. 프로그램작성순서복습 2. 주석 3. scanf_s( ) 맛보기 1. 프로그램작성순서복습 프로그래밍작성순서요약 프로젝트만들기 : 소스파일보다프로젝트를먼저생성해야함 코딩 : C 컴파일러가알아들을수있는형식으로문서작성 빌드 : 컴파일과링크를합친개념 컴파일 : 소스를컴퓨터가이해하는오브젝트파일로변환 링크 :
More information와플-4년-2호-본문-15.ps
1 2 1+2 + = = 1 1 1 +2 =(1+2)+& + *=+ = + 8 2 + = = =1 6 6 6 6 6 2 2 1 1 1 + =(1+)+& + *=+ =+1 = 2 6 1 21 1 + = + = = 1 1 1 + 1-1 1 1 + 6 6 0 1 + 1 + = = + 7 7 2 1 2 1 + =(+ )+& + *= + = 2-1 2 +2 9 9 2
More informationJava ...
컴퓨터언어 1 Java 제어문 조성일 조건문 : if, switch 어떠한조건을조사하여각기다른명령을실행 if 문, switch 문 if 문 if - else 문형식 if 문형식 if ( 조건식 ) { 명령문 1; 명령문 2;... if ( 조건식 ) { 명령문 1; 명령문 2;... else { 명령문 a; 명령문 b;... 예제 1 정수를입력받아짝수와홀수를판별하는프로그램을작성하시오.
More information강의 개요
DDL TABLE 을만들자 웹데이터베이스 TABLE 자료가저장되는공간 문자자료의경우 DB 생성시지정한 Character Set 대로저장 Table 생성시 Table 의구조를결정짓는열속성지정 열 (Clumn, Attribute) 은이름과자료형을갖는다. 자료형 : http://dev.mysql.cm/dc/refman/5.1/en/data-types.html TABLE
More informationJava + Python = Jython
Java + Python = Jython ( 피어슨에듀케이션출판사) 1. Jython 소개 본글은저자의동의없이개인적인목적이외에상업적인목적으로사용하실수없습니다. 학교본수업이외에교육체강의자료로사용하는경우에는출처를밝히셔야합니다. 또한인터넷및통신상에저자의동의없이글을공개할수없습니다. 1.1 Python 소개 Python( 파이썬) 은 C/C++/Java와같은일반프로그래밍언어를배운사람들에게는조금괴상한언어처럼보인다.
More informationVisual Basic 반복문
학습목표 반복문 For Next문, For Each Next문 Do Loop문, While End While문 구구단작성기로익히는반복문 2 5.1 반복문 5.2 구구단작성기로익히는반복문 3 반복문 주어진조건이만족하는동안또는주어진조건이만족할때까지일정구간의실행문을반복하기위해사용 For Next For Each Next Do Loop While Wend 4 For
More information1.2 자료형 (data type) 프로그램에서다루는값의형태로변수나함수를정의할때주로사용하며, 컴퓨터는선언된 자료형만큼의메모리를확보하여프로그래머에게제공한다 정수 (integer) 1) int(4 bytes) 연산범위 : (-2 31 ) ~ (2 31 /2)-
1.2 자료형 (data type) 프로그램에서다루는값의형태로변수나함수를정의할때주로사용하며, 컴퓨터는선언된 자료형만큼의메모리를확보하여프로그래머에게제공한다. 1.2.1 정수 (integer) 1) int(4 bytes) 연산범위 : (-2 31 ) ~ (2 31 /2)-1 연산범위이유 : 00000000 00000000 00000000 00000000의 32
More informationC++ Programming
C++ Programming 연산자다중정의 Seo, Doo-okok clickseo@gmail.com http://www.clickseo.com 목 차 연산자다중정의 C++ 스타일의문자열 2 연산자다중정의 연산자다중정의 단항연산자다중정의 이항연산자다중정의 cin, cout 그리고 endl C++ 스타일의문자열 3 연산자다중정의 연산자다중정의 (Operator
More information쉽게 풀어쓴 C 프로그래밍
제 3 장 C 프로그램구성요소 이번장에서학습할내용 * 주석 * 변수, 상수 * 함수 * 문장 * 출력함수 printf() * 입력함수 scanf() * 산술연산 * 대입연산 이번장에서는 C 프로그램을이루는구성요소들을살펴봅니다. 일반적인프로그램의형태 데이터를받아서 ( 입력단계 ), 데이터를처리한후에 ( 처리단계 ), 결과를화면에출력 ( 출력단계 ) 한다. 데이터입력
More information이 장에서 사용되는 MATLAB 명령어들은 비교적 복잡하므로 MATLAB 창에서 명령어를 직접 입력하지 않고 확장자가 m 인 text 파일을 작성하여 실행을 한다
이장에서사용되는 MATLAB 명령어들은비교적복잡하므로 MATLAB 창에서명령어를직접입력하지않고확장자가 m 인 text 파일을작성하여실행을한다. 즉, test.m 과같은 text 파일을만들어서 MATLAB 프로그램을작성한후실행을한다. 이와같이하면길고복잡한 MATLAB 프로그램을작성하여실행할수있고, 오류가발생하거나수정이필요한경우손쉽게수정하여실행할수있는장점이있으며,
More informationMicrosoft PowerPoint Android-SDK설치.HelloAndroid(1.0h).pptx
To be an Android Expert 문양세강원대학교 IT 대학컴퓨터학부 Eclipse (IDE) JDK Android SDK with ADT IDE: Integrated Development Environment JDK: Java Development Kit (Java SDK) ADT: Android Development Tools 2 JDK 설치 Eclipse
More informationC 프로그래밊 개요
구조체 2009 년 5 월 19 일 김경중 강의계획수정 일자계획 Quiz 실습보강 5 월 19 일 ( 화 ) 구조체 Quiz ( 함수 ) 5 월 21 일 ( 목 ) 구조체저녁 6 시 5 월 26 일 ( 화 ) 포인터 5 월 28 일 ( 목 ) 특강 (12:00-1:30) 6 월 2 일 ( 화 ) 포인터 Quiz ( 구조체 ) 저녁 6 시 6 월 4 일 ( 목
More informationMicrosoft Word - 3부A windows 환경 IVF + visual studio.doc
Visual Studio 2005 + Intel Visual Fortran 9.1 install Intel Visual Fortran 9.1 intel Visual Fortran Compiler 9.1 만설치해서 DOS 모드에서실행할수있지만, Visual Studio 2005 의 IDE 를사용하기위해서는 Visual Studio 2005 를먼저설치후 Integration
More information유니티 변수-함수.key
C# 1 or 16 (Binary or Hex) 1:1 C# C# (Java, Python, Go ) (0101010 ). (Variable) : (Value) (Variable) : (Value) ( ) (Variable) : (Value) ( ) ; (Variable) : (Value) ( ) ; = ; (Variable) : (Value) (Variable)
More informationMicrosoft PowerPoint - chap-06.pptx
쉽게풀어쓴 C 언어 Express 제 6 장조건문 컴퓨터프로그래밍기초 이번장에서학습할내용 조건문이란? if 문 if, 문 중첩 if 문 switch 문 break문 continue문 goto 문 5장까지는문장들이순차적으로실행된다고하였다. 하지만필요에따라서조건이만족되면문장의실행순서를변경할수있는기능이제공된다. 컴퓨터프로그래밍기초 2 조건문 조건에따라서여러개의실행경로가운데하나를선택
More information문서의 제목 나눔고딕B, 54pt
산업공학과를위한 프로그래밍입문 (w/ 파이썬 ) PART II : Python 활용 가천대학교 산업경영공학과 최성철교수 간단한파일다루기 [ 생각해보기 ] 우리는어떻게프로그램을시작하나? 보통은이렇게생긴아이콘을누른다! 그러나실제로는아이콘이아닌 실행파일 을실행시키는것아이콘을클릭하고오른쪽마우스클릭 속성 을선택해볼것 [ 생각해보기 ] 옆과같은화면이나올것이다대상에있는
More information데이터 시각화
데이터시각화 박창이 서울시립대학교통계학과 박창이 ( 서울시립대학교통계학과 ) 데이터시각화 1 / 22 학습내용 matplotlib 막대그래프히스토그램선그래프산점도참고 박창이 ( 서울시립대학교통계학과 ) 데이터시각화 2 / 22 matplotlib I 간단한막대그래프, 선그래프, 산점도등을그릴때유용 http://matplotlib.org 에서설치방법참고윈도우의경우명령프롬프트를관리자권한으로실행한후아래의코드실행
More informationMicrosoft PowerPoint - KNK_C03_Expr_kor
Expressions adopted from KNK C Programming : A Modern Approach Operators 연산자 C 는표현식을많이사용함 표현식은변수와상수와연산자로구성됨 C 에는연산자의종류가다양함 1. arithmetic operators ( 수식연산자 ) 2. relational operators ( 관계연산자 ) 3. logical
More informationColumns 8 through while expression {commands} 예제 1.2 (While 반복문의이용 ) >> num=0
for loop array {commands} 예제 1.1 (For 반복변수의이용 ) >> data=[3 9 45 6; 7 16-1 5] data = 3 9 45 6 7 16-1 5 >> for n=data x=n(1)-n(2) -4-7 46 1 >> for n=1:10 x(n)=sin(n*pi/10); n=10; >> x Columns 1 through 7
More information1
2/33 3/33 4/33 5/33 6/33 7/33 8/33 9/33 10/33 11/33 12/33 13/33 14/33 15/33 16/33 17/33 5) 입력을 다 했으면 확인 버튼을 클릭합니다. 6) 시작 페이지가 제대로 설정이 되었는지 살펴볼까요. 익스플로러를 종료하고 다시 실행시켜 보세요. 시작화면에 야후! 코리아 화면이 뜬다면 설정 완료..^^
More informationPowerPoint 프레젠테이션
Verilog: Finite State Machines CSED311 Lab03 Joonsung Kim, joonsung90@postech.ac.kr Finite State Machines Digital system design 시간에배운것과같습니다. Moore / Mealy machines Verilog 를이용해서어떻게구현할까? 2 Finite State
More information금오공대 컴퓨터공학전공 강의자료
C 프로그래밍프로젝트 Chap 13. 포인터와배열! 함께이해하기 2013.10.02. 오병우 컴퓨터공학과 13-1 포인터와배열의관계 Programming in C, 정재은저, 사이텍미디어. 9 장참조 ( 교재의 13-1 은읽지말것 ) 배열이름의정체 배열이름은 Compile 시의 Symbol 로서첫번째요소의주소값을나타낸다. Symbol 로서컴파일시에만유효함 실행시에는메모리에잡히지않음
More informationMicrosoft PowerPoint - gnu-w10-c-chap12
어서와 C 언어는처음이지 제 12 장 논리연산자 관계연산자의한계 if (age >= 21) /* 21
More information중간고사
중간고사 예제 1 사용자로부터받은두개의숫자 x, y 중에서큰수를찾는알고리즘을의사코드로작성하시오. Step 1: Input x, y Step 2: if (x > y) then MAX
More information프로그램의실행화면 주석 (comment) 두수의합 : 300 /* 두개의숫자의합을계산하는프로그램 */ 주석은코드를설명하는글입니다. 주석 3 가지방법의주석 주석의예 /* 한줄로된주석 */ /* 저자 : 홍길동날짜 : 2013.
쉽게풀어쓴 C 언어 Express 제 3 장 C 프로그램구성요소 이번장에서학습할내용 * 주석 * 변수, 상수 * 함수 * 문장 * 출력함수 printf() * 입력함수 scanf() * 산술연산 * 대입연산 이번장에서는 C 프로그램을이루는구성요소들을살펴봅니다. 일반적인프로그램의형태 덧셈프로그램 #1 데이터를받아서 ( 입력단계 ), 데이터를처리한후에 ( 처리단계
More informationMicrosoft PowerPoint - C++ 5 .pptx
C++ 언어프로그래밍 한밭대학교전자. 제어공학과이승호교수 연산자중복 (operator overloading) 이란? 2 1. 연산자중복이란? 1) 기존에미리정의되어있는연산자 (+, -, /, * 등 ) 들을프로그래머의의도에맞도록새롭게정의하여사용할수있도록지원하는기능 2) 연산자를특정한기능을수행하도록재정의하여사용하면여러가지이점을가질수있음 3) 하나의기능이프로그래머의의도에따라바뀌어동작하는다형성
More informationchap 5: Trees
5. Threaded Binary Tree 기본개념 n 개의노드를갖는이진트리에는 2n 개의링크가존재 2n 개의링크중에 n + 1 개의링크값은 null Null 링크를다른노드에대한포인터로대체 Threads Thread 의이용 ptr left_child = NULL 일경우, ptr left_child 를 ptr 의 inorder predecessor 를가리키도록변경
More information