msaltnet / smtm

It's a game to get money
https://smtm.msalt.net
MIT License
91 stars 96 forks source link

헬로 파이썬 #10

Closed msaltnet closed 3 years ago

msaltnet commented 3 years ago

변수

조건문

반복문

리스트

딕셔너리

함수와 클래스

msaltnet commented 3 years ago

hello python

파이썬에 대해서 쉽고 간단하게 설명을 좀 해볼까 한다. 많은 컴퓨터 서적, 특히 프로그래밍 서적들의 상당히 비슷한 구조를 갖고 있다. 프로그램의 역사부터 시작해서 자료형, 제어문의 차례로 기초부터 응용까지 샅샅이 소개하고 각 장이 끝날 때 쯔음에 연습문제가 있다. 기원이 어떻게 되는지는 모르겠지만 그다지 실용적이지는 않은것 같다. 그래서 이 책에서는 쉽고 간단하게 설명을 해보려고 한다. 모든 것을 다 외울 필요도 없고, 다 이해할 필요도 없다. 파이썬이 어떤 언어라는 것, 대충 어떻게 쓰는 것인지만 알고 넘어가도 충분하다.

흥미를 갖고 적당히 편한 마음으로 읽어 버리고, 어떻게 쓰는지 예제를 한번씩 보고 넘어가자. 어차피 우리는 자동거래 시스템을 만드는 뚜렷한 목적이 있고, 그 과정에서 학습과 복습을 반복하면서 자연스럽게 파이썬을 배우는 것이 더욱 효과적이라고 확신한다.

파이썬 시작하기

파이썬은 인터프리터 언어로써 텍스트로 작성되고 컴파일 과정이 없이 실행 된다. 인터렉티브 모드와 스크립트 모드가 있는데, 한 줄 한 줄 실행 결과를 확인하면서 프로그래밍 하는 것이 인터렉티브 모드, 파일로 저장해서 실행시키는 것이 스크립트 모드이다. 파이썬을 연습할 때는 인터렉티브 모드를 켜놓고 한 줄 한 줄 직접 실행해 보면서 이해하는 것이 좋다.

파이썬에도 다양한 자료형이 있지만 다른 언어들처럼 신경을 곤두세울 필요가 없다. 아주 편안하게 숫자, 문자, 리스트 등을 생각하는 대로 사용하면 된다. C언어나 자바 같은 경우 변수를 선언할 때부터 그 변수가 어떤 자료형인지 함께 선언을 해야 한다. 하지만 파이썬은 그런 것이 필요가 없다. 길게 생각하지 말자.

a = 10 b = 'hello world' print(a) # prints '10' print(b) # prints 'hello world'

변수를 선언 할 때 필요 없다고 해서 자료형이 없는 것이 아니다. 파이썬에서는 모든 것이 객체다. 모두 평등하다. C언어에서는 int부터 unsigned int, long, float 등 다양한 자료형이 있다. 각각을 저장할 메모리의 크기와 종류를 알아야하기 때문이다. 하지만 파이썬은 컴파일이 필요 없고, 동적으로 타입을 결정 한다. 따라서 동적으로, 필요한 때에 객체의 상태를 확인하면 된다.

쉬운것 같은데 더 어렵게 느껴지는 사람도 있을 것이다. 오랜 기간 C언어 개발자로 프로그래밍을 해왔다면 더욱이 그럴 것이다. 자료형이 없다는 것은 어쩌면 내 앞에 사람을 남자와 여자로 구분하지 않겠다는 것과 같은 혼란일 수 있다. 그냥 똑같은 인간으로 생각해줬으면 좋겠다고 해도, 그건 참 힘든 일 일수 있다.

생각해보자. 위에서 a가 무엇으로 보이는가? 숫자. 정수일것 같지 않은가? 그럼 정수라고 했을때 아무런 문제가 없다. 그럼 a는 정수다. 이런 개념을 Duck Typing 이라고 한다. 자료형에 대한 고민과 고생을 줄여서 프로그래밍에 좀 더 힘쓰자.

Duck Typing - 'If it walks like a duck and it quacks like a duck, then it must be a duck' '오리처럼 걷고, 오리처럼 꽥꽥거리면, 그것은 틀림없이 오리다.' 라는 프로그래밍 스타일 덕 타이핑 - https://docs.python.org/3/glossary.html#term-duck-typing 모든 것이 객체다 - http://python-history.blogspot.com/2009/02/first-class-everything.html

숫자

숫자를 표현하는 자료형은 int, float, complex형이 있다. 예상하는 것과 같이 정수는 int, 소수부를 값는 수는 float, 복소수는 complex이다. '/'을 사용한 나눗셈의 결과는 항상 float을 반환한다. 정수형을 원할 경우 '//'를 사용하면 된다.

2 + 2 4 50 - 56 20 (50 - 56) / 4 5.0 8 / 5 # division always returns a floating point number 1.6

거듭제곱을 할 때는 '**'를 사용하고, 변수에 넣을 때는 '=' 를 사용한다.

5 * 2 # 5 squared 25 width = 20 height = 5 9 width * height 900

문자열

문자열은 작은 따옴표과 큰 따옴표의 구분이 없다. 'hello' 와 "hello"가 같다. 작은 따옴표와 큰 따옴표를 둘 다 사용할 수 있는 것은 따옴표 자체를 문자열에서 사용할 때 매우 유용하다.

따옴표 자체를 쓰려면 앞에 역슬래시\를 붙여주면 되지만, 작은 따옴표로 구성된 문자열 안에서 큰 따옴표는 그냥 쓸 수 있고, 큰 따옴표 안에서 작은 따옴표도 마찮가지다. 아래 몇가지 예를 보자.

'spam eggs' # single quotes 'spam eggs' "doesn't" # ...or use double quotes instead "doesn't" '"Yes," they said.' '"Yes," they said.'

위와 같이 섞어 쓰지 않으면 아래와 같이 역슬래시를 사용해야 하는데 보기에도 않좋다.

'doesn\'t' # use \' to escape the single quote... "doesn't" "\"Yes,\" they said." '"Yes," they said.' '"Isn\'t," they said.' '"Isn\'t," they said.'

문자열 앞에 r을 붙이면 문자열 중간에 역슬래시를 특숫 문자로 사용하지 않고 날것 그대로(raw)사용 할 수 있다.

print('C:\some\name') # here \n means newline! C:\some ame print(r'C:\some\name') # note the r before the quote C:\some\name

여러줄의 문자열은 따옴표를 세개 연속으로 붙여서 문자열을 감싸는 것이다. '''이나 """모두 가능하다. 이때 줄 끝에 역슬래시를 붙이면 줄바꿈을 막을 수 있다.

print("""\ Usage: thingy [OPTIONS] -h Display this usage message -H hostname Hostname to connect to """)

Usage: thingy [OPTIONS] -h Display this usage message -H hostname Hostname to connect to

문자열은 + 연산자로 붙이고, * 연산자로 반복 시킬 수도 있다.

3 times 'un', followed by 'ium'

3 * 'un' + 'ium' 'unununium'

문자열은 C언어에서 배열처럼 인덱스로 접근 할 수도 있다. 음수를 넣으면 끝에서 부터 센다.

word = 'Python' word[0] # character in position 0 'P' word[-2] # second-last character 'o'

인덱스를 사용해서 문자열을 자를 수도 있다. 한 쪽을 생략할 수도 있다.

word[0:2] # characters from position 0 (included) to 2 (excluded) 'Py' word[2:5] # characters from position 2 (included) to 5 (excluded) 'tho' word[:2] # character from the beginning to position 2 (excluded) 'Py' word[4:] # characters from position 4 (included) to the end 'on' word[-2:] # characters from the second-last (included) to the end 'on'

인덱스를 사용해서 접근이 가능하지만 변경은 불가능하다. 수정이 필요하면 새로운 문자열을 만들어야 한다.

리스트

리스트는 다른 값을 하나의 덩어리로 묶는데 사용하는 자료형이다.

squares = [1, 4, 9, 16, 25] squares [1, 4, 9, 16, 25]

https://docs.python.org/ko/3/tutorial/introduction.html

msaltnet commented 3 years ago

코딩 컨벤션

개인적인 경험에 따르면 나이가 좀 있고, 경력이 많은 개발자일수록 코딩 컨벤션에 민감하다. 아마 요즘처럼 인터넷에 발달하지 않았을 때, 선배한테 엄하게 배우면서 함께 채득된 것이 아닐까 생각해본다. 이유야 어째든 코딩 컨벤션은 늘 말이 많은 주제다. 하지만 길게 고민할 만한 내용은 아니다. 잘 정리된 내용이 있다면, 적당히 선택해서 잘 따르는 것이 좋다. 좌측 통행이 좋은지 우측 통행이 좋은지 결정하는 것과 비슷하다. 길에서 서로 부딪히고 우왕좌왕 하지 않으려면, 합리적인 결정인지 의심하고 논쟁하는 것보다 구성원들이 그 결정을 잘 따르는 것이 중요하다.

파이썬에는 PEP라는 것이 있다. Python Enhancement Proposal라고 파이썬의 발전을 위해서 수많은 논의 끝에 결정된 내용들을 문서화해 놓은 것이다. 파이썬의 코딩 컨벤션에 대해서도 PEP-8에 정리해놓았으니 가능하면 그 내용을 따르자. 몇가지를 소개 하려 하는데, 이것 역시 외우거나 숙지할 필요는 없다. 프로그래밍 과정에서 다른 사람들의 코드를 보고 사용하다보면 자연스럽게 습관을 갖게 될 것이다.

  1. 들여쓰기를 위해서는 4-스페이스를 사용하고, 탭을 사용하지 마세요.

  2. 79자를 넘지 않도록 줄 넘김 하세요. 이것은 작은 화면을 가진 사용자를 돕고 큰 화면에서는 여러 코드 파일들을 나란히 볼 수 있게 합니다.

  3. 함수, 클래스, 함수 내의 큰 코드 블록 사이에 빈 줄을 넣어 분리하세요.

  4. 가능하다면, 주석은 별도의 줄로 넣으세요.

  5. 독스트링을 사용하세요.

  6. 연산자들 주변과 콤마 뒤에 스페이스를 넣고, 괄호 바로 안쪽에는 스페이스를 넣지 마세요: a = f(1, 2) + g(3, 4).

  7. 클래스와 함수들에 일관성 있는 이름을 붙이세요; 관례는 클래스의 경우 UpperCamelCase, 함수와 메서드의 경우 lowercase_with_underscores입니다. 첫 번째 메서드 인자의 이름으로는 항상 self를 사용하세요.

PEP-8 - https://www.python.org/dev/peps/pep-0008/

튜플

앞에서 리스트와 문자열의 인덱싱이나 슬라이싱 연산이 비슷하다는 것을 알 수 있었다. 문자열과 리스트는 튜플과 함께 시퀀스 자료형으로 분류된다. 튜플은 여러개의 아이템을 담고 있지만 일반적으로 다른 형태의 아이템을 담고 있다는 점이 리스트와 다르며, 문자열처럼 불변의 값을 갖는 다는 점도 리스트와는 다르다. 리스트나 문자열처럼 인덱싱으로 개별 아이템에 접근이 가능하고, 패킹, 언패킹으로 변수에 대입이 가능한데, 이것은 다른 시퀀스 형도 마찬가지로 사용 가능하다.

>>> t = 12345, 54321, 'hello!' # t라는 튜플 변수가 생성된다
>>> t[0] # 인덱싱
12345
>>> t
(12345, 54321, 'hello!')
>>> # 튜플은 다른 자료형에 포함될 수 있다
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # 튜플은 불변이다. 값을 변경할 수 없다
... t[0] = 88888
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # 하지만 값을 변경할 수 있는 오브젝트를 포함할 수는 있다
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])
>>> x, y, z = t # 튜플 언 패킹, 순서대로 대입된다. 갯수가 
>>> x, y = t # 수가 맞지 않으면 언 패킹 에러가 발생한다

집합

집합은 수학에서 집합을 위해 존재하는 자료형이다. 집합은 중복되는 요소가 없는 순서 없는 컬렉션이다. 기본적으로 포함 여부의 판단과 중복 엔트리 제거에 사용된다. 합집합, 교집합, 차집합, 대칭 차집합과 같은 수학적인 연산들도 지원한다.

집합을 만들 때는 중괄호나 set() 함수를 사용한다.

>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket)                      # 중복된 apple, orange는 하나만 들어간다
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket                 # 집합에 포함되는지 빠르게 검사가 가능하다
True
>>> 'crabgrass' in basket
False

>>> # 2단어 중에 하나뿐인 문자를 찾는 방법
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a                                  # a에 하나뿐인 문자들
{'a', 'r', 'b', 'c', 'd'}
>>> a - b                              # a에는 있고 b에는 없는 문자들
{'r', 'd', 'b'}
>>> a | b                              # a 또는 b에 있는 문자들
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b                              # a와 b 모두에 있는 문자들
{'a', 'c'}
>>> a ^ b                              # a와 b 한쪽에만 있는 문자들
{'r', 'd', 'b', 'm', 'z', 'l'}

딕셔너리

딕셔너리는 키와 값이 하나의 쌍을 이루는 아이템을 갖는 자료형이다. 키는 고유한 값이어야 하며, 문자열 외에도 숫자나 튜플도 키로 사용할 수 있다. 단, 튜플이 가변 객체를 포함하고 있으면 키로 사용할 수 없다.

딕셔너리는 빈 중괄호로 생성할 수 있고, 쉼표로 분리된 키:값 쌍을 넣어서 초기화된 딕셔너리를 생성할 수 있다. 키로 저장하고, 키로 값을 추출할 뿐만 아니라 del을 사용해서 아이템을 삭제할 수있다. 사용되고 있는 키를 사용해서 저장하면 기존 값에 덮어씌워지고, 존재하지 않는 키를 사용해서 아이템을 가져오려고 하면 에러를 발생한다.

딕셔너리에 list(d)를 수행하면 모든 키의 리스트를 삽입 순서대로 돌려준다. 정렬을 원할 경우는 sorted(d)를 사용하면 된다. 키로 아이템의 존재여부를 확인 하기 위해는 in 키워드를 사용하면 된다.

>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'jack': 4098, 'sape': 4139, 'guido': 4127}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'jack': 4098, 'guido': 4127, 'irv': 4127}
>>> list(tel)
['jack', 'guido', 'irv']
>>> sorted(tel)
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
>>> 'jack' not in tel
False

반복문 응용하기

딕셔너리를 반복문에 사용할 때 items()를 사용하면 키와 값을 모두 얻을 수 있다.

>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
...     print(k, v)
...
gallahad the pure
robin the brave

시퀀스 자료형을 반복문에 사용할 때, enumerate() 함수를 사용하면 위치 인덱스와 대응하는 값을 동시에 얻을 수 있다.

>>> for i, v in enumerate(['tic', 'tac', 'toe']):
...     print(i, v)
...
0 tic
1 tac
2 toe

시퀀스를 거꾸로 사용하려면, 먼저 정방향으로 시퀀스를 지정한 다음에 reversed() 함수를 호출하면 된다.

>>> for i in reversed(range(1, 10, 2)):
...     print(i)
...
9
7
5
3
1

정렬된 순서로 시퀀스를 사용할 때는, sorted() 함수를 사용해서 소스를 변경하지 않고도 정렬된 새 리스트를 받을 수 있다.

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for i in sorted(basket):
...     print(i)
...
apple
apple
banana
orange
orange
pear

중복된 요소를 제거하고 싶을때는 집합을 사용하면 된다.

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
...     print(f)
...
apple
banana
orange
pear

모듈

파이썬에는 인터렉티브 모드와 스크립트 모드가 있다고 했다. 인터렉티브 모드는 파이썬 인터프리터를 실행하여 바로 바로 응답을 받는 것이고, 스크립트 모드는 파일로 작성해서 실행시키는 것이다. 간단한 테스트는 인터렉티브 모드에서 할 수 있지만 결국 우리가 만드는 프로그램은 스크립트 형태가 될 것이다. 스크립트로 만들어서 재사용하고 공유할 수도 있게 하기 위해 모듈이라는 개념이 도입되었다.

모듈은 .py 확장자 파일로 저장되고 모듈내에서 모듈의 이름은 전역변수 name으로 제공된다. 아래 내용을 sum.py로 저장해보자.

# math.py 에 저장해서 사용해보자
def sum(a, b):
    return a + b

아래와 같이 import해서 sum 함수를 사용 할 수 있다.

>>> import math
>>> math.sum(10, 5)

모듈에는 함수 외에도 실행 가능한 코드가 들어 있을 수 있다. 모듈이 import 될 때 1회만 수행되고, 각 모듈은 자신만의 심볼 테이블을 가지고 있어서 전역변수와 충돌하지 않는다. 당연히 모듈은 다른 모듈을 import할 수 있다. 일반적으로 import문은 파일의 가장 위에 위치하지만 꼭 그렇지 않아도 된다.

모듈에 있는 이름을 심볼테이블에 직접 import 할 수도 있다. 전역 변수처럼 바로 사용 할 수 있다.

>>> from math import sum
>>> sum(10, 5)

*을 사용해서 모든 것을 import 할 수도 있다.

>>> from sum import *
>>> sum(10, 5)

as 를 써서 이름을 바꿔서 import 할 수도 있다.

>>> import math as cal
>>> cal.sum(10, 5)

모듈 말고 다른 심볼을 이름을 정할 수도 있다.

>>> from math import sum as total
>>> total(10, 5)

출력을 위한 문자열 형식

그동안 print()를 사용해서 단순한 출력을 했다. 하지만 좀 더 복잡하게 변수를 문자열 중간에 넣어서 출력할 수도 있다. f또는 F를 문자열 앞에 붙여줌으로써 문자열안에 중괄호로 둘러싸인 변수를 넣을 수 있다. 이것을 포맷 문자열 리터럴이라고 한다.

좀 더 정교하게 표현식을 설정할 수도 있다. 다음은 소숫점 이하 세자리로 반올림하는 예제이다.

>>> import math
>>> print(f'The value of pi is approximately {math.pi:.3f}.')
The value of pi is approximately 3.142.

: 뒤에 정수를 전달하면 최소 문자폭을 결정할 수 있다. d를 붙이면 뒤쪽으로 정렬이 가능하다.

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
...     print(f'{name:10} ==> {phone:10d}')
...
Sjoerd     ==>       4127
Jack       ==>       4098
Dcab       ==>       7678

str.format()을 이용해서 포매팅을 할 수도 있다. 기본적으로 빈 중괄호를 넣어서 차례대로 넣을 수 있다.

>>> print('We are the {} who say "{}!"'.format('knights', 'Ni'))
We are the knights who say "Ni!"

번호를 붙여서 순서를 조정할 수도 있다.

>>> print('{0} and {1}'.format('spam', 'eggs'))
spam and eggs
>>> print('{1} and {0}'.format('spam', 'eggs'))
eggs and spam

인자를 사용해서 적용할 수도 있다.

>>> print('This {food} is {adjective}.'.format(
...       food='spam', adjective='absolutely horrible'))
This spam is absolutely horrible.