파이썬 기초와 Ipython, jupyter notebook
C:\Users\Desktop\project\basic>python hello.py
hello.py
__main__
C:\Users\Desktop\project\basic>ipython
In [1]: %run hello.py
hello.py
__main__
In [2]: an_apple = 27
In [3]: an_example = 42
an 입력하고 tap 키 누르면 자동 완성 기능 제공
자기관찰(인트로스펙션 introspection)
In [3]: b = [1, 2, 3]
In [4]: b?
Type: list
String form: [1, 2, 3]
Length: 3
Docstring:
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list.
The argument must be an iterable if specified.
In [5]: print?
Signature: print(*args, sep=' ', end='\n', file=None, flush=False)
Docstring:
Prints the values to a stream, or to sys.stdout by default.
sep
string inserted between values, default a space.
end
string appended after the last value, default a newline.
file
a file-like object (stream); defaults to the current sys.stdout.
flush
whether to forcibly flush the stream.
Type: builtin_function_or_method
변수 이름 앞이나 뒤에 물음표를 붙이면 그 객체에 대한 일반 정보 출력
In [7]: def add_numbers(a, b):
...: """
...: Add two numbers together
...: Returns
...: ------
...: the sumL type of arguments
...: """
...: return a + b
...:
In [8]: add_numbers?
Signature: add_numbers(a, b)
Docstring:
Add two numbers together
Returns
------
the sumL type of arguments
File: c:\users\desktop\project\basic\<ipython-input-7-004085b61198>
Type: function
별표(*)로 문자열을 둘러싸게 되면 해당 문자열이 포함된 모든 이름을 보여 줌
In [9]: import numpy as np
In [10]: np.*load*?
np.__loader__
np.load
np.loadtxt
In [11]: a = b
In [12]: a.append(4)
In [13]: a
Out[13]: [1, 2, 3, 4]
In [14]: b
Out[14]: [1, 2, 3, 4]
변수에 값을 할당하는 것은 한 이름이 하나의 객체로 연결되므로 바인딩이라고 부름
값이 할당된 변수 이름은 때때로 종속 변수라고 부르기도 함
In [15]: def append_element(some_list, element):
...: some_list.append(element)
...:
In [16]: data = [1, 2, 3]
In [17]: append_element(data, 4)
In [18]: data
Out[18]: [1, 2, 3, 4]
In [23]: a = 4.5
In [24]: b = 2
In [25]: # 문자열 출력 형식을 지정한다. 나중에 자세히 살펴본다
In [26]: print('a is {}, b is {}'.format(type(a), type(b)))
a is <class 'float'>, b is <class 'int'>
모듈 import
C:\Users\Desktop\project\basic>copy con some_module.py
# some_module.py
PI = 3.14159
def f(x):
return x + 2
def g(a, b):
return a + b
^Z # 코드 입력 후 ctrl + Z
1개 파일이 복사되었습니다.
In [2]: import some_module
In [3]: result = some_module.f(5)
In [4]:
In [4]: pi = some_module.PI
In [5]: pi
Out[5]: 3.14159
In [6]: # 또는
In [7]: from some_module import g, PI
In [8]: result = g(5, PI)
In [9]: result
Out[9]: 8.14159
문자열
In [33]: animals = '''
...: cat
...: dog
...: fish
...: '''
In [34]: animals
Out[34]: '\ncat\ndog\nfish\n'
In [35]: animals.count('\n')
Out[35]: 4
In [36]: a = 'this is a string'
In [37]: a[10] = 'f'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[37], line 1
----> 1 a[10] = 'f'
TypeError: 'str' object does not support item assignment
파이썬의 문자열은 변경이 불가능
> replace 같은 메서드를 사용해 변경된 새로운 문자열을 생성해야 함
In [38]: b = a.replace('string', 'longer string')
In [39]: b
Out[39]: 'this is a longer string'
In [40]: a
Out[40]: 'this is a string'
작업 이후 변수 a는 변경되지 않음
역슬래시(\)는 이스케이프 문자로 개행 문자 \n이나 유니코드 문자 같은 특수한 목적의 문자를 나타내기 위해 사용
역슬래시를 나타내려면 역슬래시 자체를 이스케이프해야 함
In [54]: s = '12\34'
In [55]: s
Out[55]: '12\x1c'
In [56]: s = '12\\34'
In [57]: s
Out[57]: '12\\34'
특수 문자 없이 역슬래시가 많이 포함된 문자열 나타낼 때, 혹은 특수문자를 그대로 나타내도록 할 때
In [52]: s = r'this\has\no\special\characters'
In [53]: s
Out[53]: 'this\\has\\no\\special\\characters'
코드 앞에 r을 붙임
In [58]: template = '{0:.2f} {1:s} are worth US${2:d}'
{0:.2f}는 첫 번째 인수를 소수점 아래 두 자리까지만 표시하는 부동소수점 형태로 출력하라는 의미
{1:s}는 두 번째 인수를 문자열로 포맷하라는 의미
{2:d}는 세 번째 인수를 정수로 포맷하라는 의미
In [59]: template.format(88.46, 'Argentine Pesos', 1)
Out[59]: '88.46 Argentine Pesos are worth US$1'
포맷 매개변수를 통해 대치하고 싶은 인수를 format 메서드에 전달
파이썬 3.6부터 문자열 포맷을 편리하게 지정할 수 있는 f-string 기능 추가됨
f-string을 만들려면 문자열을 감싸는 따옴표 앞에 f를 붙이면 됨
In [60]: amount = 10
In [61]: rate = 88.46
In [62]: currency = 'Pesos'
In [63]: result = f'{amount} {currency} is worth US${amount / rate}'
In [64]: f'{amount} {currency} is worth US${amount / rate:.2f}'
Out[64]: '10 Pesos is worth US$0.11'
위 문자열 템플릿과 같은 방법으로 각 표현식 뒤에 포맷 지정 가능
정렬
In [34]: a = [7, 2, 5, 1, 3]
In [35]: a.sort()
In [36]: a
Out[36]: [1, 2, 3, 5, 7]
In [37]: b = ['saw', 'small', 'He', 'foxes', 'six']
In [38]: b.sort(key=len)
In [39]: b
Out[39]: ['He', 'saw', 'six', 'small', 'foxes']
sort는 몇 가지 옵션을 제공하는데 그중 하나는 사용할 값을 반환하는 함수
슬라이싱
# 원하는 크기만큼 자르기
In [40]: seq = [7, 2, 3, 7, 5, 6, 0, 1]
In [41]: seq[1:5]
Out[41]: [2, 3, 7, 5]
# 다른 순차 자료형을 대입할 수 O
In [42]: seq[3:5] = [6, 3]
In [43]: seq
Out[43]: [7, 2, 3, 6, 3, 6, 0, 1]
색인의 시작(start) 위치에 있는 값은 포함, 끝(stop)은 포함 x
슬라이싱 결과의 개수는 stop - start
In [44]: seq[-4:]
Out[44]: [3, 6, 0, 1]
In [45]: seq[-6:-2]
Out[45]: [3, 6, 3, 6]
음수 색인은 순차 자료형의 끝에서부터 위치를 나타냄
In [46]: seq[::2]
Out[46]: [7, 3, 3, 0]
In [47]: seq[::-1]
Out[47]: [1, 0, 6, 3, 6, 3, 2, 7]
두 번째 콜론 다음에 간격(step) 지정할 수 있음
값으로 -1을 사용하면 리스트나 튜플을 역순으로 반환
딕셔너리
In [49]: empty_dict = {}
In [50]: d1 = {'a': 'some value', 'b': [1, 2, 3, 4]}
In [51]: d1
Out[51]: {'a': 'some value', 'b': [1, 2, 3, 4]}
In [52]: d1[7] = 'an integer'
In [53]: d1
Out[53]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer'}
In [54]: d1['b']
Out[54]: [1, 2, 3, 4]
In [55]: 'b' in d1
Out[55]: True
In [56]: d1[[10, 20]] = [100, 200]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[56], line 1
----> 1 d1[[10, 20]] = [100, 200]
TypeError: unhashable type: 'list'
다른 프로그래밍 언어에서는 해시 맵 또는 연관 배열(associative array)로 알려져 있음 키-값 쌍을 저장
리스트는 키로 사용할 수 없음
del 예약어나 pop 메서드(값을 반환함과 동시에 해당 키 삭제)를 통해 딕셔너리 값을 삭제할 수 있
In [57]: d1[5] = 'some value'
In [58]: d1
Out[58]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer', 5: 'some value'}
In [59]: d1['dummy'] = 'another value'
In [60]: d1
Out[60]:
{'a': 'some value',
'b': [1, 2, 3, 4],
7: 'an integer',
5: 'some value',
'dummy': 'another value'}
In [61]: del d1[5]
In [62]: d1
Out[62]:
{'a': 'some value',
'b': [1, 2, 3, 4],
7: 'an integer',
'dummy': 'another value'}
In [63]: ret = d1.pop('dummy')
In [64]: ret
Out[64]: 'another value'
In [65]: d1
Out[65]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer'}
keys와 values 메서드는 각각 키와 값이 담긴 이터레이터 반환, 키의 순서는 삽입 순서에 따라 다름
이러한 함수는 키와 값을 각각 동일한 순서로 출력
In [66]: list(d1.keys())
Out[66]: ['a', 'b', 7]
In [67]: list(d1.values())
Out[67]: ['some value', [1, 2, 3, 4], 'an integer']
키와 값에 대해 반복 작업을 해야 하는 경우 items 메서드를 사용하면 키-값 쌍을 갖는 튜플로 사용할 수 있음
In [68]: list(d1.items())
Out[68]: [('a', 'some value'), ('b', [1, 2, 3, 4]), (7, 'an integer')]
update 메서드를 사용하면 하나의 딕셔너리를 다른 딕셔너리와 합칠 수 있음
In [69]: d1.update({'b': 'foo', 'c': 12})
In [70]: d1
Out[70]: {'a': 'some value', 'b': 'foo', 7: 'an integer', 'c': 12}
이미 존재하는 키에 대해 update를 호출하면 이전 값은 사라짐
순차 자료형에서 딕셔너리 생성
In [71]: tuples = zip(range(5), reversed(range(5)))
In [72]: tuples
Out[72]: <zip at 0x2287a0e2780>
In [73]: mapping = dict(tuples)
In [74]: mapping
Out[74]: {0: 4, 1: 3, 2: 2, 3: 1, 4: 0}
본질적으로 딕셔너리는 두 개짜리 튜플로 구성됨
dict 함수가 두 개짜리 튜플의 리스트를 인수로 받아 딕셔너리를 생성
(딕셔너리가 만들어지는 과정)
기본값
In [75]: words = ['apple', 'bat', 'bar', 'atom', 'book']
In [76]: by_letter = {}
In [77]: for word in words:
...: letter = word[0]
...: if letter not in by_letter:
...: by_letter[letter] = [word]
...: else:
...: by_letter[letter].append(word)
...:
In [78]: by_letter
Out[78]: {'a': ['apple', 'atom'], 'b': ['bat', 'bar', 'book']}
setdefault 메서드 사용 목적
In [79]: by_letter = {}
In [80]: for word in words:
...: letter = word[0]
...: by_letter.setdefault(letter, []).append(word)
...:
In [81]: by_letter
Out[81]: {'a': ['apple', 'atom'], 'b': ['bat', 'bar', 'book']}
내장 collections 모듈에는 위 과정을 좀 더 쉽게 만드는 defaultdict 클래스가 있음
자료형 혹은 딕셔너리의 각 슬롯에 담길 기본값을 생성하는 함수를 넘겨 딕셔너리 생성
In [85]: from collections import defaultdict
In [86]: for word in words:
...: by_letter[word[0]].append(word)
...:
In [87]: by_letter
Out[87]: defaultdict(list, {'a': ['apple', 'atom'], 'b': ['bat', 'bar', 'book']})
In [91]: keys = ['a', 'b', 'c', 'd']
In [92]: x = dict.fromkeys(keys, 0)
In [93]: x
Out[93]: {'a': 0, 'b': 0, 'c': 0, 'd': 0}
In [94]: x['z']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[94], line 1
----> 1 x['z']
KeyError: 'z'
In [95]: from collections import defaultdict
In [96]: y = defaultdict(int)
In [97]: y['z']
Out[97]: 0
In [98]: int()
Out[98]: 0
In [99]: z = defaultdict(lambda: 'python')
In [100]: z['a']
Out[100]: 'python'
In [101]: z[0]
Out[101]: 'python'
유효한 딕셔너리 키
딕셔너리의 값으로는 어떤 파이썬 객체든 가능하지만 키는 스칼라 자료형(정수, 실수, 문자열)이나 튜플(튜플에 저장된 값 또한 바뀌지 않는 객체여야 함)처럼 값이 바뀌지 않는 객체만 가능
기술적으로는 해시가 가능(hashability)해야 함, 어떤 객체가 해시가 가능한지는(딕셔너리의 키로 사용할 수 있는지) hash 함수를 사용해 검사할 수 있음
In [103]: hash('string')
Out[103]: -3594434936365532107
In [104]: hash((1, 2, (2, 3)))
Out[104]: -9209053662355515447
In [105]: hash((1, 2, [2, 3]))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[105], line 1
----> 1 hash((1, 2, [2, 3]))
TypeError: unhashable type: 'list'
비가역으로 해시 > 원래 넣었던 객체는 불가능, 길이는 모두 같음
집합
# 집합
In [106]: set([2, 2, 2, 1, 3, 3])
Out[106]: {1, 2, 3}
In [107]: a = {1, 2, 3, 4, 5}
In [108]: b = {3, 4, 5, 6, 7, 8}
# 합집합
In [109]: a.union(b)
Out[109]: {1, 2, 3, 4, 5, 6, 7, 8}
In [110]: a|b
Out[110]: {1, 2, 3, 4, 5, 6, 7, 8}
# 교집합
In [111]: a.intersection(b)
Out[111]: {3, 4, 5}
In [112]: a & b
Out[112]: {3, 4, 5}
# 부분집합, 상위집합
In [113]: a_set = {1, 2, 3, 4, 5}
In [114]: {1, 2, 3}.issubset(a_set)
Out[114]: True
In [115]: a_set.issuperset({1, 2, 3})
Out[115]: True
# 집합의 내용이 같다면 두 집합은 동일(순서가 없기 때문)
# 리스트나 튜플은 False
In [116]: {1, 2, 3} == {3, 2, 1}
Out[116]: True
딕셔너리도 순서가 없기 때문에 셸 창에 {1: 'cat', 2: 'dog'} == {2: 'dog', 1: 'cat'} 입력했을 때 True 출력
내장 순차 자료형 함수
1. enumerate
순차 자료형에서 현재 아이템의 index를 함께 추적할 때 사용
In [117]: a = [38, 21, 53, 62, 19]
In [118]: for i, v in enumerate(a):
...: print(i, v)
...:
0 38
1 21
2 53
3 62
4 19
2. sorted
정렬된 새로운 순차 자료형 반환
In [119]: sorted([7, 1, 2, 6, 0, 3, 2])
Out[119]: [0, 1, 2, 2, 3, 6, 7]
In [120]: sorted('horse race')
Out[120]: [' ', 'a', 'c', 'e', 'e', 'h', 'o', 'r', 'r', 's']
In [194]: a = [7, 1, 2, 6, 0, 3, 2]
In [195]: sorted(a)
Out[195]: [0, 1, 2, 2, 3, 6, 7]
In [196]: a
Out[196]: [7, 1, 2, 6, 0, 3, 2]
In [197]: a.sort()
In [198]: a
Out[198]: [0, 1, 2, 2, 3, 6, 7]
3. zip
여러 개의 리스트나 튜플 또는 다른 순차 자료형을 서로 짝지어 튜플 리스트 생성
In [126]: seq1 = ['foo', 'bar', 'baz']
In [127]: seq2 = ['one', 'two', 'three']
In [128]: zipped = zip(seq1, seq2)
In [129]: list(zipped)
Out[129]: [('foo', 'one'), ('bar', 'two'), ('baz', 'three')]
In [130]: seq3 = [False, True]
In [131]: list(zip(seq1, seq2, seq3))
Out[131]: [('foo', 'one', False), ('bar', 'two', True)]
In [132]: for index, (a, b) in enumerate(zip(seq1, seq2)):
...: print(f'{index}: {a}, {b}')
...:
0: foo, one
1: bar, two
2: baz, three
In [133]: a
Out[133]: 'baz'
In [134]: b
Out[134]: 'three'
리스트, 집합, 딕셔너리 표기
리스트 표기법
In [135]: strings = ['a', 'as', 'bat', 'car', 'dove', 'python']
In [136]: [x.upper() for x in strings if len(x) > 2]
Out[136]: ['BAT', 'CAR', 'DOVE', 'PYTHON']
필터 조건 생략 가능, 문자열 리스트가 있다면 위 코드처럼 문자열의 길이가 2 이하인 문자열은 제외하고 나머지를 대문자로 변환 가능
집합과 딕셔너리도 동일한 방식 적용 가능
리스트 내 문자열들의 길이를 담고 있는 집합을 생성하려면 집합 표기법을 이용해 다음과 같이 처리
In [141]: unique_lengths = {len(x) for x in strings}
In [142]: unique_lengths
Out[142]: {1, 2, 3, 4, 6}
map 함수를 이용해 함수적으로도 표현 가능
In [143]: set(map(len, strings))
Out[143]: {1, 2, 3, 4, 6}
딕셔너리 표기법 예제: 리스트에서 문자열의 위치를 담고 있는 딕셔너리 생성
In [144]: loc_mapping = {value: index for index, value in enumerate(strings)}
In [145]: loc_mapping
Out[145]: {'a': 0, 'as': 1, 'bat': 2, 'car': 3, 'dove': 4, 'python': 5}
중첩된 리스트 표기법
각 이름에서 알파벳 a가 두 개 이상 포함된 이름의 리스트 구한다고 했을 때 다음과 같은 반복문으로 리스트를 구할 수 있음
In [146]: all_data = [['John', 'Emily', 'Michael', 'Mary', 'Stevev'], ['Maria', 'Juan', 'Javier', 'Natalia', 'Pilar']]
In [147]: names_of_interest = []
In [148]: for names in all_data:
...: enough_as = [name for name in names if name.count('a') >= 2]
...: names_of_interest.extend(enough_as)
...:
In [149]: names_of_interest
Out[149]: ['Maria', 'Natalia']
위 코드 전체를 중첩된 리스트 표기법을 이용해 한 번에 구현할 수 있음
In [151]: result = [name for names in all_data for name in names
...: if name.count('a') >= 2]
In [152]:
In [152]: result
Out[152]: ['Maria', 'Natalia']
리스트 표기법에서 for 부분은 중첩의 순서에 따라 나열되며 필터 조건은 끝에 위치함
숫자 튜플이 담긴 리스트를 단순한 리스트로 변환하는 예제
In [153]: some_tuples = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
In [154]: flattened = [x for tup in some_tuples for x in tup]
In [155]: flattened
Out[155]: [1, 2, 3, 4, 5, 6, 7, 8, 9]
함수
In [157]: def my_function(x, y):
...: return x + y
...:
In [158]: my_function(1, 2)
Out[158]: 3
In [159]: result = my_function(1, 2)
In [160]: result
Out[160]: 3
함수 블록이 끝날 때까지 return 문이 없다면 자동으로 None이 반환됨
In [161]: def function_without_return(x):
...: print(x)
...:
In [162]: result = function_without_return('hello!')
hello!
In [163]: print(result)
None
각 함수는 여러 개의 위치 인수와 키워드 인수를 받을 수 있음
키워드 인수는 기본값이나 선택적인 인수로 흔히 사용됨
In [164]: def my_function2(x, y, z=1.5):
...: if z > 1:
...: return z * (x + y)
...: else:
...: return z / (x + y)
...:
In [165]: my_function2(5, 6, z=0.7)
Out[165]: 0.06363636363636363
In [166]: my_function2(3.14, 7, z=3.5)
Out[166]: 35.49
In [167]: my_function2(10, 20)
Out[167]: 45.0
키워드 인수는 선택 사항이지만 함수를 호출할 때 위치 인수는 반드시 지정해야 함
함수의 키워드 인수는 항상 위치 인수 다음에 와야 한다는 규칙이 있음
네임스페이스, 스코프, 지역함수
함수는 전역(global)과 지역(local), 두 가지 스코프(scope)에서 변수를 참조
변수의 스코프를 설명하는 다른 용어로 네임스페이스가 있음, 함수에서 선언된 변수는 기본적으로 모두 지역 네임스페이스에 속함
In [168]: def func():
...: a = []
...: for i in range(5):
...: a.append(i)
...:
In [169]: def func():
...: a = []
...: for i in range(5):
...: a.append(i)
...: print(a)
...:
In [170]: func()
[0, 1, 2, 3, 4]
In [171]: print(a)
baz
In [172]: a = []
In [173]: def func():
...: for i in range(5):
...: a.append(i)
...:
In [174]: func()
In [175]: a
Out[175]: [0, 1, 2, 3, 4]
In [176]: func()
In [177]: a
Out[177]: [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
In [178]: a = None
In [179]: def bind_a_variable():
...: global a
...: a = []
...: bind_a_variable()
In [180]:
In [180]: print(a)
[]
In [181]: print(a.append('apple'))
None
In [182]: a
Out[182]: ['apple']
global 예약어의 사용은 권장되지 않음
여러 값 반환
In [183]: def f():
...: a = 5
...: b = 6
...: c = 7
...: return a, b, c
...:
In [184]: a, b, c = f()
In [185]: f()
Out[185]: (5, 6, 7)
In [187]: x
Out[187]: {'a': 0, 'b': 0, 'c': 0, 'd': 0}
In [188]: x, y, z = (5, 6, 7)
In [189]: x
Out[189]: 5
In [190]: def f():
...: a = 5
...: b = 6
...: c = 7
...: return {'a': a, 'b': b, 'c': c}
...:
In [191]: result = f()
In [192]: result
Out[192]: {'a': 5, 'b': 6, 'c': 7}
경우에 따라 딕셔너리를 반환하는 방식이 더 유용할 수 있음