[[TableOfContents]] == 개요 == * [https://docs.python.org/3/tutorial]의 내용을 [열파참/금요일]에서 정리. * 번역이 아닌 정리다보니, 내용의 차이가 있을 수 있음... 이 아니라 있음. * 스터디시만 사용하는 독스: http://goo.gl/11ZcFB == 내용 == === Whetting Your Appetite === === Using the Python Interpreter === === An Informal Introduction to Python === * {{{#}}} : 주석 ==== Using Python as a Calculator ==== ===== Numbers ===== * python은 계산기처럼 쓸 수 있음. * +, -, *, /, (), **, //, %가 존재. * //연산자는 몫을 리턴. * {{{x ** y}}} 연산자는 x의 y승 == {{{pow(x, y)}}}. * -x = x negated * int / int = float이니 조심. * {{{_}}}: 마지막에 출력된 값을 의미. * 복소수도 내장으로 지원함: {{{complex(real, imaginary)}}} * {{{divmod(x, y)}}} => {{{(x // y, x % y)}}} 이런 형태로 출력당함 * {{{round(x, y)}}}: 숫자x에서 소수점 자리수를 y개수만 남김. ===== Strings ===== * String은 ‘...’ 혹은 “...”사용. 차이는 없음. * 다른 언어와 같이{{{\}}}를 이용해 특수 문자를 입력 가능. * {{{\t}}}, {{{\n}}}, {{{\’}}} 등. * 중간에 있는’를 무효화 시키기 위해서 \를 붙이거나 큰따옴표를 사용 * 단지 “...” 안의 ‘ 는 허용. ‘...’ 안의 “ 허용. escape 문자 필요없음 * ’r’을 붙이면 {{{\}}}를 특수문자가 아닌 일반 문자로 표현. {{{ >>> print('C:\some\name') # \n을 개행문자로 인식 C:\some ame >>> print(r'C:\some\name') # r을 앞에 붙인다 C:\some\name }}} * String을 {{{+}}}로 더하고, {{{*}}}로 반복할 수 있다. * {{{“““....”””}}} 여러 줄을 허용하는 문자열 * {{{“some” “thing”}}} == {{{“something”}}} * 오직 literals 끼리 적용된다. * 변수, 수식에서 적용되지 않음 * 긴 string을 여러 줄에 걸쳐서 쓸 때 사용하면 유용 {{{ >>> prefix = 'Py' >>> prefix 'thon' SyntaxError: invalid syntax >>> ('un' * 3) 'ium' SyntaxError: invalid syntax }}} * index를 이용해서 각 chr에 접근 가능하며, 음수도 가능. {{{ +---+---+---+---+---+---+ | P | y | t | h | o | n | +---+---+---+---+---+---+ 0 1 2 3 4 5 6 -6 -5 -4 -3 -2 -1 }}} * slicing: {{{[start:end:step]}}}. start는 포함되며, end는 포함되지 않고, 각 항목은 생략 가능. {{{ word = 'Python' >>> word[0:2] 'Py' >>> word[:2] + word[2:] 'Python' >>> word[:2] 'Py' >>> word[-2:] 'on' >>> word[:] ‘Python’ }}} * {{{len(s)}}}: string과 기타 등등의 원소의 개수를 반환 ===== Lists ===== * Python이 가지는 여러가지 자료를 묶는 방식 중 가장 가변적인 형태 * []로 묶어서 표현. {{{ >>> squares = [1, 4, 9, 16, 25] >>> squares [1, 4, 9, 16, 25] }}} * {{{[n]}}}으로 index n에 해당하는 데이터에 접근 * + 로 복수의 list를 append할 수 있다. * {{{len()}}}: list와 기타 등등의 원소의 개수를 반환. * Slicing * String이랑 동일하게 적용. {{{>>> a = ['a', 'b', 'c'] >>> n = [1, 2, 3] >>> x = [a, n] >>> x [['a', 'b', 'c'], [1, 2, 3]] >>> x[0] ['a', 'b', 'c'] >>> x[0][1] 'b' }}} ==== First Steps Towards Programming ==== * {{{a, b = b, a+b}}} : 우변을 연산하고 좌변의 대응하는 위치에 맞추어서 대입한다. * Indentation 잘못하면 안 돼요. === More Control Flow Tools === === Data Structures === === Modules === === Input and Output === ==== Fancier Output Formatting ==== * {{{str()}}} vs {{{repr()}}} * {{{str()}}}: 사람이 읽기 위한 용도로 string으로 변환 * {{{repr()}}}: {{{eval()}}}을 사용하기 위한 용도로 string으로 변환 {{{ >>> s = 'Hello, world.' >>> str(s) 'Hello, world.' >>> repr(s) "'Hello, world.'" }}} * {{{str.format()}}} method를 이용하면 노가다를 뛰지 않고도 깔끔하게 출력이 가능 {{{ >>> for x in range(1, 3): ... print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x)) ... 1 1 1 2 4 8 3 9 27 }}} {{{ >>> print('The story of {1}, {0}, and {other}.'.format('Manfred','Bill', other='Georg')) The story of Bill, Manfred, and Georg. }}} {{{ >>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678} >>> print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; ' ... 'Dcab: {0[Dcab]:d}'.format(table)) Jack: 4098; Sjoerd: 4127; Dcab: 8637678 }}} {{{ >>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678} >>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table)) Jack: 4098; Sjoerd: 4127; Dcab: 8637678 }}} * {{{vars()}}}를 이용하면 local variables를 담은 dictionary를 얻을 수 있음. 위의 예제와 쓰면 궁합이 좋음. * {{{str.rjust(n)}}}, {{{str.ljust(n)}}}, {{{str.center(n)}}}: n사이즈에 맞게 정렬된 string을 반환. str이 이미 n보다 길면 무시. * 이와 같은 문제를 해결하기 위해 {{{str.ljust(n)[:n]}}} 같은 짓을 가능. * {{{str.zfill(n)}}}: n사이즈에 맞게 0이 삽입된 string을 반환. ===== Old string formatting ===== * {{{%typeIndicator}}} * 구식이다. {{{ print(‘The value of PI is %5.3f.’ % math.pi) }}} ==== Reading and Writing Files ==== * {{{open(filename, mode)}}}: 파일 열기 * mode * ‘r’: 읽기 (기본값) * ‘w’: 쓰기 * ‘a’: 이어쓰기 * ‘r+’,’w+’: 쓰고 읽기 * ‘b’: 바이너리로 열기 (없으면 텍스트로 읽음) * binary vs text * text mode에서는 line ending을 플랫폼에 맞는 형식으로 변환. * 따라서 text가 아닌 파일을 text 모드로 열면 파일이 변형될 수 있음. ===== Methods of File Objects ===== * {{{read(size)}}} * size만큼 파일을 읽는다. size가 지정되지 않거나 음수면 메모리가 허용하는 만큼 읽음. * 끝에 도달하면 빈 string인 ‘’를 반환 * {{{readline()}}} / {{{readlines()}}} * 한 줄 읽어오는 메소드/한줄씩 묶어서 리스트로 제공하는 메소드 * list(file)로도 readlines와 같은 효과 * 다음과 같이 for문을 이용할 수도 있음: {{{ for line in f: print(line, end=’’) }}} * {{{write(string)}}} * 파일에 string을 씁니다. string만 가능하니 다른 것을 쓰고 싶다면 str(object)로 변환 후 이용. * {{{seek(index,from)}}} : * from * 0 : 파일의 시작점을 기준으로 * 1 : 현재 보고 있는 바이트를 기준으로(tell()로 보이는 그거) * 2 : 파일의 마지막 바이트를 기준으로 * {{{tell()}}} * 파일 내의 현재 지정하고 있는 바이트 위치를 알려줌 * {{{close()}}} * 파일을 닫음. 닫고 나서 해당 파일을 쓰려고 하면 오류가 남. * {{{closed}}} * NOT A METHOD * 닫혔는지 여부를 boolean으로 알려줌 ===== Saving structured data with json ===== * json = [http://json.org JavaScript Object Notation] * {{{import json}}} * {{{json.load(json file)}}} 도 파일 읽기 시스템. 읽고 난 뒤에는 마지막으로 간다. 고로 여러번 읽을 수 없다. * {{{json.dumps(obj)}}}: obj를 json 형식으로 전환 * {{{json.dump(obj, file)}}} : file에 쓰기 === Errors and Exceptions === ==== Syntax Errors ==== * {{{SyntaxError}}} - 문법 오류. 파싱을 하다 문제가 생기면 발생 * 자주 틀리는 문법 오류 * 들여쓰기 * 따옴표 * {{{:}}} ==== Exceptions ==== * 문법적으로는 맞지만 실행하려고 시도하는 중에 발생하는 에러. * {{{ZeroDivisionError}}}, {{{NameError}}}, {{{TypeError}}}, [https://docs.python.org/3.4/library/exceptions.html#bltin-exceptions 기타 등등] * Built-in Exception의 경우 발생시 Exception이름과 이유가 출력됨. ==== Handling Exceptions ==== * 어떠한 Exception들에 대해 개발자가 선택적으로 다룰 수 있음. java와 유사. {{{ try: x = 1 / 0 except ZeroDivisionError: print(“...”) }}} * 여러 개의 예외처리는 튜플로 가능하다. {{{ except (RuntimeError, TypeError, NameError): pass }}} * {{{as}}} 키워드를 이용해서 객체 이용 가능 {{{ except OSError as err: print("OS error: {0}".format(err)) }}} * Error 명을 적지 않고 {{{except:}}}와 같이 쓰면 모든 Error에 대해 처리. 단, 매우 신중하게 사용해야 하며, 다음처럼 메시지를 출력하고 다시 Error를 선언하는 식으로 쓸 수 있음. {{{ except: print("Unexpected error") raise }}} * {{{else:}}} 구문: try 구문에서 exception이 발생되지 않은 경우 실행 * built-in Exception class들은 인자를 넘겨줄 경우 {{{instance.args}}} 로 접근이 가능하며, {{{__str__()}}}은 이 {{{.args}}}를 출력해줌. {{{ >>> try: ... raise Exception('spam', 'eggs') ... except Exception as inst: ... print(type(inst)) ... print(inst.args) ... print(inst) ('spam', 'eggs') ('spam', 'eggs') }}} ==== Raising Exceptions ==== * {{{raise}}} 구문: 프로그래머가 원하는 Exception을 일으킨다. * Exception을 상속받은 Class 들만 가능하다 * {{{class className(Exception):}}} 상속 방법 ==== User-defined Exceptions ==== * Exception Class를 상속하여 새로운 Exception class를 만들 수 있다. * {{{__init__()}}}, {{{__str__()}}}이 기본적으로 구현되어있으나, override 가능. * 가능하면 ‘~Error’ 라는 이름으로 하는 것이 좋음. ==== Defining Clean-up Actions ==== * {{{finally:}}} - try 문이 완전히 종료되기 직전에 반드시 실행되는 내용. * except 문으로 사용자가 지정한 Exception이 아닌 다른 Exception이 발생할 경우 finally 문이 실행된 이후 다시 해당 Exception을 발생시킨다. * try문이 끝나고 else문이 있으면 else문이 실행된 다음에 실행 됨. ==== Predefined Clean-up Actions ==== {{{ with open("myfile.txt") as f: for line in f: print(line, end="") }}} * with 에서 나오면 open된 file을 close 해준다. * 조금 더 일반적으로 설명하자면, with 구문을 벗어나면 사용된 객체를 자동으로 정리해줌. * {{{__exit__()}}}, {{{__enter__()}}}가 구현되어 있는 class의 경우 with 구문을 사용 할 수 있으며, 다른 built-in class들도 구현이 되어 있음. === Classes === ==== A Word About Names and Objects ==== class도 Object이다. ==== Python Scopes and Namespaces ==== * statements * nonlocal * global ===== Scopes and Namespaces Example ===== {{{ def scope_test(): def do_local(): spam = "local spam" def do_nonlocal(): nonlocal spam spam = "nonlocal spam" def do_global(): global spam spam = "global spam" spam = "test spam" do_local() print("After local assignment:", spam) do_nonlocal() print("After nonlocal assignment:", spam) do_global() print("After global assignment:", spam) scope_test() print("In global scope:", spam) }}} Result {{{ After local assignment: test spam After nonlocal assignment: nonlocal spam After global assignment: nonlocal spam In global scope: global spam }}} ==== A First Look at Classes ==== ===== Class Definition Syntax ===== def와 유사. {{{ class MyClass: """A simple example class""" i = 12345 def f(self): return 'hello world' }}} ===== Class Objects ===== class objects는 다음과 같은 2가지의 작업이 가능하다. * attribute reference * {{{MyClass.i}}}, {{{MyClass.f}}}, {{{MyClass.__doc__}}}과 같이 선언된 class의 attribute에 접근. * instantiation * {{{x= MyClass()}}} 와 같은 문법으로 인스턴스화 가능. * 인스턴스화 될 때 {{{__init__(self)}}} method가 자동으로 실행. 따라서 객체의 초기화를 진행할 수 있음. * {{{__init__(self, x, y)}}}처럼 인자를 받을 수도 있음. * overloading을 시도했으나 overriding이 되버림. default parameter를 이용해야 하는 듯? ===== Instance Objects ===== instance object는 attribute reference만 가능. * data attribute * method * object에 종속된 function ===== Method Objects ===== * {{{x.f()}}} == {{{MyClass.f(x)}}} * {{{x.f}}}는 method object이기 때문에 다음과 같이 대입 후 사용 가능. {{{ xf = x.f xf() }}} ===== Class and Instance Variables ===== {{{ class Dog: kind = 'canine' # 클래스 변수 def __init__(self, name): self.name = name # 인스턴스 변수 }}} 클래스 변수는 모든 인스턴스가 공유하고, 인스턴스 변수는 각 객체마다 따로 지니는 변수. 인스턴스 변수를 클래스 변수에 선언하지 않도록 주의 ==== Random Remarks ==== * Data, Method, Function 등등이 서로 충돌이 일어날 수 있으니 적합한 네이밍 (카멜케이스, 헝가리안 등)을 사용하는 것이 좋음. * python에서는 C의 struct와 같은 추상 데이터 타입을 완전히 구현하는 것이 불가능하다. * 사용자들이 임의로 변경을 할 수 있기 때문 * method 첫 인자인 ‘self’는 다른 이름으로 둘 수도 있지만, 가독성을 위해 냅두는 것이 좋음. * class 속성으로 들어가있는 function은 반드시 안에서 구현이 될 필요 없이 대입을 해도 사용 할 수 있음. {{{ # Function defined outside the class def f1(self, x, y): return min(x, x+y) class C: f = f1 def g(self): return 'hello world' h = g }}} * method에서 다른 method를 부르고 싶을 경우 {{{self.another_method()}}} 식으로 호출. * 모든 객체는 {{{object.__class__}}}를 동해 class를 확인할 수 있음. ==== Inheritance ==== {{{ class DerivedClassName(BaseClassName): ... }}} * {{{isinstance()}}} : 인스턴스인지 확인 * {{{isinstance(obj, int)}}} 는 True * {{{issubclass()}}} : 상속을 확인 * {{{issubclass(bool, int)}}} 는 True * {{{issubclass(float, int)}}} 는 False ===== Multiple Inheritance ===== * 다중상속이 가능하다. {{{ class DerivedClassName(Base1, Base2, Base3): }}} * method, variable등을 호출 할 때 가장 먼저 DerivedClass를 탐색하고, 왼쪽부터 차례대로 찾아 다님. * 실제로는 더 복잡한 방법으로 진행된다고는 하는데... ==== Private Variables ==== * {{{_variable}}}은 ‘밖에서 쓰이면 안된다는’ variable이라는 약속. 쓸 수는 있으나. 쓰지 말자. * Private object = __objectname * object 이름 앞에 __ 붙이면 private. {{{ class Mapping: def __init__(self, iterable): self.items_list = [] self.__update(iterable) def update(self, iterable): for item in iterable: self.items_list.append(item) __update = update # private copy of original update() method class MappingSubclass(Mapping): def update(self, keys, values): # provides new signature for update() # but does not break __init__() for item in zip(keys, values): self.items_list.append(item) }}} * 그러니 실제로 Private가 아님 * object._classname__spam 으로 접근 가능하다 ==== Odds and Ends ==== {{{ class Employee: pass john = Employee() # john 이라는 이름의 빈 Employee를 만듬 john.name = 'John Doe' john.dept = 'computer lab' john.salary = 1000 }}} ==== Exceptions Are Classes Too ==== {{{raise Class}}} == {{{raise Class()}}} {{{raise Instance}}} {{{ class CustomException(Exception): pass }}} * 하나의 try문에 여러 except 문이 있을 경우, 가장 위에서부터 해당 class의 인스턴스인지 확인. ==== Iterators ==== * {{{for}}}문은 실행시 object의 {{{iter()}}}를 호출해 나온 iterator object를 사용. * iterator object는 다음 element를 return하고, 더이상 element가 없으면 {{{StropIteration}}} exception을 raise하는 {{{__next__()}}} method를 가지고 있음. * {{{__next__()}}}은 {{{next()}}} built-in function을 통해서도 부를 수 있음. {{{ >>> s = 'abc' >>> it = iter(s) >>> it >>> next(it) 'a' >>> next(it) 'b' >>> next(it) 'c' >>> next(it) Traceback (most recent call last): File "", line 1, in ? next(it) StopIteration }}} {{{ class Reverse: """Iterator for looping over a sequence backwards.""" def __init__(self, data): self.data = data self.index = len(data) def __iter__(self): return self def __next__(self): if self.index == 0: raise StopIteration self.index = self.index - 1 return self.data[self.index] }}} {{{ >>> rev = Reverse('spam') >>> iter(rev) <__main__.Reverse object at 0x00A1DB50> >>> for char in rev: ... print(char) ... m a p s }}} ==== Generators ==== * Generator는 iterator를 만듦. 일반적인 function가 유사하지만 return 대신 yield를 사용. {{{next()}}} 가 호출될 때 마다 실행을 멈춘 자리에서 다시 작업을 수행. * {{{__iter__()}}} 와 {{{__next__()}}} method가 자동으로 생성되서 코드가 간단해지고, 각 call 사이마다 local variables과 실행 상태를 저장하고, generator가 끝난 이후 자동으로 {{{StropIteration}}}이 raise되는 것이 특징. 따라서 일반적인 구현보다 쉬워짐. {{{ def reverse(data): for index in range(len(data)-1, -1, -1): yield data[index] }}} {{{ >>> for char in reverse('golf'): ... print(char) ... f l o g }}} ==== Generator Expressions ==== 예제 : {{{ >>> sum(i*i for i in range(10)) # sum of squares 285 >>> xvec = [10, 20, 30] >>> yvec = [7, 5, 3] >>> sum(x*y for x,y in zip(xvec, yvec)) # dot product 260 >>> data = 'golf' >>> list(data[i] for i in range(len(data)-1, -1, -1)) ['f', 'l', 'o', 'g'] }}} === Brief Tour of the Standard Library === ==== Operating System Interface ==== * {{{os}}} : os 모듈은 os와 상호작용하는 함수를 제공 * {{{os.getcwd()}}} : 현재 디렉토리 리턴 {{{cwd}}}와 같음 * {{{os.chdir(path)}}} : 현재 디렉토리를 path로 변경 * {{{os.system(command)}}} : command를 시스템 쉘에서 실행 * {{{shutil}}} : os에 비해 더 상위 인터페이스를 제공 * {{{shutil.copyfile(src, dst, *, follow_symlinks=True)}}} : 파일 copy * {{{shutil.move(src, dst)}}} : src를 dst로 이동시킴 ==== File Wildcards ==== * {{{glob}}} 모듈은 와일드카드({{{*}}}, {{{?}}}) 검색을 통한 파일 이름이 담긴 list를 반환하는 function을 가지고 있음. * {{{glob.glob(pathname)}}} : 검색한 파일 리스트를 보여준다 ==== Command Line Arguments ==== * {{{sys.argv)}}}: 인자({{{python demo.py one two three}}}) 를 list로 반환 ==== Error Output Redirection and Program Termination ==== * {{{sys}}} 모듈은 stdin, stdout, stderr 속성을 가지고 있으며, 파일이나 다른 output으로 redirection이 가능. {{{sys.stderr.write('Warning, log file not found starting a new one\n')}}} ==== String Pattern Matching ==== {{{re}}} 모듈은 정규표현식 (regular expression) 도구들을 제공. * {{{re.findall(pattern, string)}}}: 매칭되는 문자들을 list로 반환 * {{{re.sub(pattern, repl, string)}}}: 매칭되는 문자들을 repl로 변환한 string을 반환 ==== Mathematics ==== * {{{math}}} 모듈은 float에 대한 C라이브러리 함수에 접근 가능하다. * {{{math.cos(x)}}} : cos(x)값을 반환 * {{{math.log(x[, base])}}} : base를 밑으로 한 log값을 반환. base가 없을 시 밑은 e가 된다. * {{{random}}} 모듈은 무작위 선택에 대한 함수를 제공한다. * {{{random.random}}} : 무작위의 float을 반환 * {{{random.randrange(number)}}} : range(number) 에서 정수 하나 반납 ==== Internet Access ==== {{{urllib.request}}} 모듈은 인터넷 연결을 통한 작업들을 쉽게 할 수 있는 함수들이 있음. * email, ftp, html, url, 등 로컬 호스트에 메일서버가 있다면, {{{stmplib}}} 모듈을 이용해서 메일을 보낼 수 있음 ==== Dates and Times ==== {{{datetime}}} 모듈은 시간과 시간대를 다룸. * {{{datetime.date}}} 클래스는 특정한 날짜를 저장 (2013, 4, 5) * {{{date.strftime}}}을 이용하면 포멧을 이용해서 출력 가능. {{{ >>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.") '12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.' }}} * {{{datetime.timedelta}}} 클래스는 기간을 저장 {{{date(2014, 2, 1) - date(2014, 1, 1)}}} == {{{datetime.timedelta(31)}}} ==== Data Compression ==== zlib, gzip, bz2, lzma, zipfile, tarfile 등의 모듈에서 압축을 지원한다. (여기서는 zlib을 사용) * {{{zlib.compress(byte)}}} : byte을 압축 * {{{zlib.decompress(byte)}}}: 압축한 byte을 압축하기 전으로 풀기 * {{{type(b”saeou”)}}} = * {{{type(r”saeouha”)}}} = ==== Performance Measurement ==== * timeit = 작은 코드의 실행 시간을 측정하기 위한 도구 * {{{Timer(“code”, “code”, …).timeit()}}} : 가장 왼쪽의 코드(str)를 실행 -> 삭제 -> 없을 때까지 루프 * {{{Timer(“code”).timeit()}}} 으로 무한 루프도 가능하다. 안 끝날 뿐. ==== Quality Control ==== * {{{doctest}}}모듈은 docstring안에 있는 테스트 코드를 실행시킴. {{{ def average(values): """Computes the arithmetic mean of a list of numbers. >>> print(average([20, 30, 70])) 40.0 """ return sum(values) / len(values) import doctest doctest.testmod() # automatically validate the embedded tests }}} * {{{unittest}}} 모듈은 {{{doctest}}}보다는 복잡하지만, 더 상세한 테스트를 진행할 수 있음. {{{ import unittest class TestStatisticalFunctions(unittest.TestCase): def test_average(self): self.assertEqual(average([20, 30, 70]), 40.0) self.assertEqual(round(average([1, 5, 7]), 1), 4.3) with self.assertRaises(ZeroDivisionError): average([]) with self.assertRaises(TypeError): average(20, 30, 70) unittest.main() # Calling from the command line invokes all tests }}} ==== Batteries Included ==== * python은 이런 식으로 쓰기 쉬운 모듈들이 많음.