Module을 통으로 import를 하나, 그 중에 일부만 import를 하나 memory 측면에선 전혀 차이가 없다만,
Global namespace에서 어떤 이름이 올라와 있냐의 차이만 있었다.
---> math가 올라와 있어서 math.sqrt 등 dot을 통해 접근하냐?
vs from math import sqrt 해서 sqrt가 떡하니 global에 올라와 있냐의 차이!를 알자
요번엔 List , Loop 등 슬슬 Python의 메인 영역으로 들어가보자. 복기 시작!
1. List
Data들은 보통 그룹화가 되어있다. 이제 슬슬 python으로 group화된 Data를 다루는 법을 배워봅시다.
- List는 순서가 있다. (Ordered O)
- 대괄호로 표현하며, 다양한 method가 있다.
list 안에 element를 바꿔줄 땐, 기존 "yesong" box의 value가 바뀌는 것이 아니라 "kakyeong"이라는 Memory가 생기고, students[1] 이 그것을 pointing 하면서 Data 수정이 일어난다.
※ List 안에 저장되는 element 들의 Data type(boolean, int ..)은 다양하게 저장할 수도 있지만 권장X!
※ C, C++에선 List(Container)에 여러 가지 data type을 아~예 넣질 못함!
from typing import List
def avg(L:list[float]) -> float:
return L[0]
avg([1,2,3])
<권장 표시법>
위와 같이 Operator의 경우 A 자체만 가지고 놀지만 아래 Method의 경우 Parameter가 필요할 때, Parameter를 적어준다.
사실 Slicing 부분이 Python의 가장 큰 매력이지 않을까 싶다. C / C++ 하다 보면 이 Slicing이 너무나 그립다..
2. List - Copy and Alias ( 쌍둥이냐=copy 별명=alias냐의 차이 )
Copy가 죽으면 나는 살지만, Alias가 죽으면 나도 죽는다..
# 요것은 Copy의 일종
A_copy = A[:]
print(A_copy)
A_copy[0] = 1234
print(A_copy)
print(A)
[999, 100, 8, 7, 6, 1, 0, -4, -123]
[1234, 100, 8, 7, 6, 1, 0, -4, -123]
[999, 100, 8, 7, 6, 1, 0, -4, -123]
# 요것은 Alias 일종
A_copy = A
print(A_copy)
A_copy[0] = 1234
print(A_copy)
print(A)
[999, 100, 8, 7, 6, 1, 0, -4, -123]
[1234, 100, 8, 7, 6, 1, 0, -4, -123]
[1234, 100, 8, 7, 6, 1, 0, -4, -123]
# Alias 여도 삭제한다고 원본이 삭제되지 않는다. 수정만 째깍째깍 반영되고
A=[1, 8, 100, -123, 5, 6, 7, 0, -4]
A_copy = A
print(A_copy)
A_copy[0] = 1234
print(A_copy)
del A_copy
print(A)
print(A_copy)
[1, 8, 100, -123, 5, 6, 7, 0, -4]
[1234, 8, 100, -123, 5, 6, 7, 0, -4]
[1234, 8, 100, -123, 5, 6, 7, 0, -4]
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[137], line 8
6 del A_copy
7 print(A)
----> 8 print(A_copy)
NameError: name 'A_copy' is not defined
# 위 사항, 적용되는 지 혼자 실험해보기..된다
def del_last(L:list[int])->list :
del L[-1]
test2 = [1,2,3]
del_last(test2)
print(test2)
[1, 2]
위 현상은 Local Variable "L"이 우리의 Global Varialbe list를 Alias로 포인팅하면서 발생한 case이다. Memory 구조는 아래와 같다.
즉, Slicing 을 써서 Copying을 쓰는 것이 일반적으론 안전하다.
Function argument를 넘길 때도 원본을 넘기면 alias로 넘어가니까 copy를 만들어서 넘기던지, 아니면 잘 유념하고 있던지 하자
3. Loops - For loop
Repetition을 하는 건 귀찮으니까 써주는 것이 for loop이다. 사실,, 코딩하다보면 젤 많이 쓰이는 스킬이 아닐까 싶다.
For Loop 역시 세미콜론으로 구분하기에 Indentation이 필수다.
#에시로 간단히 알아보는 for loop
course = ["A","B","C"]
for x in course:
print("IN LOOP, There is : ",x)
IN LOOP, There is : A
IN LOOP, There is : B
IN LOOP, There is : C
List가 아닌 String에서도 for loop를 돌릴 수 있다는 것 유의!
name = "Bgg-LEE"
for ch in name:
if(ch.isupper()): #케릭터가 대문자인지 확인
print(ch)
B
L
E
E
이번엔 제일 많이 쓰이는 Range of Numbers를 for loop 돌리기!
하나 주의하면 좋은 건, range는 숫자가 0부터 시작해서 range(N)의 경우 실제 0~N-1까지 N개의 숫자가 loop를 돈다.
#Case 별로 확인해보기
print("case1")
for x in range(10):
print(x)
print("\ncase2")
for x in range(3,10):
print(x)
print("\ncase3")
for x in range(4,10,2): # step, 간격을 2 씩 줘봤다
print(x)
print("\ncase4")
for x in range(10,1,-2): # 뒤로 빽 하며 세는 것도 가능
print(x)
case1
0
1
2
3
4
5
6
7
8
9
case2
3
4
5
6
7
8
9
case3
4
6
8
case4
10
8
6
4
2
그리고 이건 C언어의 pointer 중 call by reference, call by value와 비슷한 느낌인데,
for loop로 list 의 값을 바꿔주고 싶을 땐 아래와 같이 값만 바꿔주면 안 되고, index를 통해서 접근해야 한다.
index를 바꿔줘야 실제 list 원본이 바뀐다는 것!
일종의 포인터, call by reference라는 개념이 Python에선 index접근으로 이뤄진다.
list modifing 할 때 유의해아 하는 점이다!
values = [11,22,33]
for x in range(len(values)):
values[x] = 2*values[x]
values
[22, 44, 66]
if문과 마찬가지로 for문도 nested하게 표현이 충분히 가능하다.
사실 이렇게 하면 나중에 나올 표현으로 Time complexity가 O(N^2)가 되어 느려지긴 하는데,
이걸 어떻게 줄일지는 알고리즘적으로 풀어갈 문제라 나도 더 숙달이 필요한 부분 ㅠㅠ
list1 = ["A","B","C"]
list2 = ["X","Y","Z"]
cnt = 1
for i in range(len(list1)):
for j in range(len(list2)):
print(cnt,"번째 조합",i,j)
cnt = cnt+1
1 번째 조합 0 0
2 번째 조합 0 1
3 번째 조합 0 2
4 번째 조합 1 0
5 번째 조합 1 1
6 번째 조합 1 2
7 번째 조합 2 0
8 번째 조합 2 1
9 번째 조합 2 2
4. Loops - While loop
While Loop의 표현식은 다음과 같다.
설정해둔 Condition이 True라면 계속 해서 block 부분을 실행한다는 것. 이 역시 세미콜론이 쓰이는 구문이기 때문에 Indentation으로 Block 부분 구분이 필수다.
그리고 loop가 언젠간 멈출 수 있게 block을 finite하게 잘 설정해줘야 한다.
아니면 그 유명한 Infinite loop, 무한루프에 빠지게 된다 ㅠㅠ 이럴 땐 Ctrl + C로 프로그램 끝내고 다시 수정해야함!
#이런식으로 while문을 통해 user에게 data 입력받기도 가능하다.
text = ""
list1 = []
while text != "quit":
text = input("Gimme your MBTI, 끝내고 싶으면 quit 입력:")
if text != "quit":
list1.append(text)
list1
Gimme your MBTI, 끝내고 싶으면 quit 입력:ENTP
Gimme your MBTI, 끝내고 싶으면 quit 입력:ISTJ
Gimme your MBTI, 끝내고 싶으면 quit 입력:ABCD
Gimme your MBTI, 끝내고 싶으면 quit 입력:quit
['ENTP', 'ISTJ', 'ABCD']
- Loop문 Control 하기 with Break & Continue
Break를 if문과 결합시키면 유용하게 while문을 컨트롤 할 수 있다.
이렇게 대문자가 언제 첫 번째로 나타나는지 체크하는 코드를 짤 수도 있고!
text = "asdAbasdqweDSVEAsdr"
# find the first upper letter in the given text
for ch in text:
if ch.isupper():
print("Index:",text.find(ch),",letter:",ch)
break
Index: 3 ,letter: A
※참고로, 모든 대문자 letter에 대해서 index 중복을 피하면서 대문자의 index, 값을 출력하는 방법은 아래와 같다.
#방법 1 그냥 idx를 for문으로 돌리기
text = "asdAbasdqweDSVEAsdr"
for i in range(len(text)):
ch = text[i]
if ch.isupper():
print("index :",i,",value:",ch)
index : 3 ,value: A
index : 11 ,value: D
index : 12 ,value: S
index : 13 ,value: V
index : 14 ,value: E
index : 15 ,value: A
#방법 2 enumerate 라는 것을 사용하기
text = "asdAbasdqweDSVEAsdr"
# find the first upper letter in the given text
for index, ch in enumerate(text):
if ch.isupper() and index not in found_indices:
print("Index:", index, ",letter:", ch)
Index: 3 ,letter: A
Index: 11 ,letter: D
Index: 12 ,letter: S
Index: 13 ,letter: V
Index: 14 ,letter: E
Index: 15 ,letter: A
※ enumerate(list)는 list의 index와 value를 각각 반환해주어 중복을 피할 수 있게 해준다.
Continue문은 아래와 같이 쓸 수 있다.
Continue를 만나면 그 순간, 그 아래 부분을 무시하고 다시 다음 loop로 올라간다.loop가 완전히 끝나는 건 for문을 다 돌거나 while문의 조건이 false가 되거나 loop가 Break를 만났을 때다.
5. Sets : 기본적인 골자는 중복을 무시한다. (Ordered X, Distinct)
Set은 중복제거 + 순서상관X 이다. 내가 정한 순서대로 값이 저장되는 것이 아니라 index를 통한 접근이 불가하다.
대신에 Mutable한 structure라서 list처럼 data 추가/제거 등 수정이 가능하다.
setA
setA = {'a','d','c','a'}
setA
{'a', 'c', 'd'}
list를 set으로 만들어 줄 수도 있다. 중복은 제거되고 순서도 무의미해지긴 하지만!
listA = [3,2,4,2,5]
setA = set(listA)
setA
{2, 3, 4, 5}
set도 list와 같이 역시나 for문을 돌릴 수 있다. 하지만 UNORDERED 구조니까
for문이 뱉는 순서는 의미가 없고, 알 수도 없다.
setB = {1,5,2,1,5,6,7,0,-5,100}
for x in setB:
print(x)
0
1
2
100
5
6
7
-5
Set의 Method
list와 달리 append(맨 뒤에 추가), insert(특정 위치에 추가) 가 아니라, 순서가 없기 때문에 특정 위치를 정할 수가 없다.
그래서 method 이름도 그냥 add / remove이다.
Method의 이름들도 가만 보고 있으면 다~ 이유가 있다는 것
앞서, Set에도 add, remove method를 적용하면 값을 추가, 제거할 수 있어서 mutable하다고 했지만,
Set안에 있는 각각의 value에 대해선 Imuutable content만 가질 수 있도록 허용한다. 즉 List와 같이 바꿀 수 있는 것을 set의 값으로 입력시킬 수가 없다.
이 이유는, set의 가장 강력한 무기인 Hashing을 쓰기 위함인데. hashing은 특정 data를 찾을 때 원 큐에 찾을 수 있도록 해주는 search기법이다. 이 hashing의 조건이 바로 set의 조건처럼 값들이 unordered 되어 있고, 값 자체가 바뀌는 것이 허용되지 않는다는 조건이 필요하다.
set의 투박한 특징들을 한 번에 trade - off로 커버할만큼 hashing은 search 속도 면에서 큰 장점을 갖는다.
list가 특정 값을 찾기 위해서 list 전체의 data를 싹 순회할 때, hashing은 그 값을 한 번에 딱 찾아낸다.
setC = {"C","ABC",3,False}
setC
{3, 'ABC', 'C', False}
1,2,3
setC = {"C","ABC",3,False,[1,2,3]} #set에 list를 넣으려니까 error발생.unhashable type!
setC
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[110], line 1
----> 1 setC = {"C","ABC",3,False,[1,2,3]}
2 setC
TypeError: unhashable type: 'list'
setC = {"C","ABC",3,False,{1,2,1}}
## 마찬가지로 set 자체로 remove,add 등으로 바뀔 수 있는 container라서 error발생
setC
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[111], line 1
----> 1 setC = {"C","ABC",3,False,{1,2,1}}
2 setC
TypeError: unhashable type: 'set'
6. Tuple (Ordered O, Immutable)
List와 같이 순서가 있다. Ordered 구조라 Index로 접근가능하지만, add / remove 등으로 data를 바꾸는 것은 불가능!
Tuple을 Declare 할 때는 소괄호를 쓰는데 그냥 (8) 이렇게 하면 그냥 괄호 안에 숫자가 있는 수학적표현이다.
그래서 value를 하나만 쓸 때는 (8,) 이렇게 쉼표를 적어준다.
#튜플은 내부 Data를 바꿀 수 없다!
tup2 = ("A",3,True)
tup2[0] = "B"
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[121], line 2
1 tup2 = ("A",3,True)
----> 2 tup2[0] = "B"
TypeError: 'tuple' object does not support item assignment
※ 그런데, Tuple은 Mutable한 data를 받을 순 있다. 얘네를 바꾸는 건 또 가능 ㅎㅎ 유의하자
tup3 = ("A",[1,2,3],"C")
print(tup3)
tup3[1][0] = "Changed" #tuple 안을 파고들어서 value를 바꾸는 거 가능
print(tup3)
('A', [1, 2, 3], 'C')
('A', ['Changed', 2, 3], 'C')
7. Dictionaries ( 처음 배울 땐 별거 아닌 거 같았는데, 나중에 가면 갈수록 은근 많이 쓰인다.. )
Ordered O + Mutable without Duplicate 구조이다. Key/Value로 이루어져 있으며 Key는 List의 Index와 같은 역할이라고 보면 된다.
그냥 중괄호를 쓰면 Empty Dictionary를 나타낸다. 이게 우리가 set을 쓸 때 set()으로 Empty Set을 표현했던 이유!
#모든 것은 Key 기준으로 이루어진다.
dictA = {"A":1,"B":2}
dictA["C"] = 3
print(dictA)
dictA["A"] = 100
print(dictA)
print("C" in dictA)
{'A': 1, 'B': 2, 'C': 3}
{'A': 100, 'B': 2, 'C': 3}
True
for 문도 key 값 기준으로 돌릴 수 있다.
for x in dictA:
print(x,dictA[x])
A 100
B 2
C 3
Dictionary의 각종 method들도 알아두면 유용하다.
'In' Operation도 Key 값 기준으로 적용한다.
간단한 예제 case, dictionary의 key - value pair를 swap한 grade_inv를 만들어보자
grades = {"A":1,"B":5,"C":3,"D":3}
grades_inv = {}
for x in grades:
if grades[x] not in grades_inv.keys():
grades_inv[grades[x]] = [x]
else :
grades_inv[grades[x]].append(x)
grades_inv
{1: ['A'], 5: ['B'], 3: ['C', 'D']}
Key는 중복되지 않는데, value는 중복된다는 것을 체험해 볼 수 있는 Case였다!
8. Mutability
List, Set, Tuple, Dictionary의 Mutability를 체크해보자. OX 퀴즈에도 많이 나오고 기본적으로 이해하고 있으면 편하다.
Mutable 한 Container의 특징은 1) element 들을 추가하거나 삭제할 수 있다. 2) 각 element를 가르키는 화살표를 바꿀 수 있다, 즉 element의 value를 수정할 수 있다는 것이다.
List : Mutable / Tuple : Immutalbe(※ element가 mutable하면 그 놈은 수정 가능) 즉 tuple은 Immutable하지만 그것의 element는 mutable 하다. / Set : Mutable 한 container인데(값의 pointing을 바꿀 수 없는데도 일단 mutable하다고 하네) Tuple과 반대로 각 element들은 Immutable(Hashable)하다.
그냥 값 변경(추가,삭제,수정)이 가능만 하면 Mutable container라고 표현한다.
Python 대부분의 일은 for loop , in operator(뭔가를 찾는 것)이 set와 dictionary에서 굉장히 빠르다. Hashing이라는 것이 주는 이점이 그만큼 크다는 것!
set value, dict key가 immutable 하다는 조건은 까다롭지만 그것들이 data를 찾을 때 순차적으로 쭉~ 훑는 것이 아닌 Hashing skill을 쓰는 것을 가능케 하니까 빠른 써칭이 가능하게 해준다.
Dict의 key 자체가 index! Set의 element 찾기와 같은 원리다. One shot One kill!
- E. O. D -
'SW 만학도 > Python' 카테고리의 다른 글
Review 5 - Python OOP(Objected Oriented Programming) (0) | 2024.07.05 |
---|---|
Review 4 - Python File I/O (0) | 2024.07.02 |
Review 2 - Python의 기본 Module , Class (0) | 2024.07.01 |
Review 1 - Python programming basics (1) | 2024.07.01 |
13. Data Structures (Trees) (1) | 2024.03.25 |