강의내용
Variables
a = 8 같이 선언하는 순간 "메모리에 물리적으로 공간이 할당". 폰 노이만 구조.
int
float
str (string)
bool (boolean)
Dynamic typing
속도는 느린데 편함. 사용자에게는 쉬운언어.
실수형에서 정수형으로 변하면 "내림"
10.8 도 소수점 다 잘려서 10
float은 소수점 이진수 저장 방식 써서 0.1을 저장하려면
0.1 * 2 = 0.2 -> 0
0.2 * 2 = 0.4 -> 0
0.4 * 2 = 0.8 -> 0
0.8 * 2 = 1.6 -> 1
0.6 * 2 = 1.2 -> 1
0.2 * 2 = 0.4 -> 0
...
0.0001100110011....(2)
단순 실수도 이진수로 변환하면 무한 소수가 된다.
cities = ['서울', '부산', '인천', '대구', '대전', '광주', '울산', '수원']
cities[0:5] 라고하면 0부터 4까지 출력. [0:5) 형태.
cities[-1] 하면 맨 끝 '수원' 출력. cities[-9:] 하면 -9가 '서울'이라 전부 출력.
cities[0:5:2] 의 2는 step. cities[::-1] 하면 거꾸로.
리스트 2개를 더하면 concatnation. 그냥 그대로 붙임.
color = ['yellow', 'blue', 'green']
color * 2. 그대로 붙혀줌.
"blue" in color 는 true 반환. 없으면 false 반환.
color.append("white")
color.extend(["black", "purple"]) concatnation과 비슷.
color.remove("white")
del color[0]
a = ["color", 1, 0.2] 같이 다른 타입들도 같이 저장 가능.
a = [color, 1, 0.2] 같이 하면 a 는 [['blue', 'green', ..], 1, 0.2] 같이 저장도 가능. 메모리 주소값을 저장하는 거라.
리스트 변수에는 "리스트 주소값이 저장".
그래서 b=a 하고 a.sort() 하면 b도 sort()
a[3] = 100 하면 b[3]도 100이 됨.
b = a[:] 하면 복사개념
패킹, 언패킹
t = [1,2,3]
a, b, c = t
리스트 안에 리스트를 만들어 행렬(Marix) 생성
kor_score = [49,79,20,100,80]
math_score = [43,59,85,30,90]
eng_score = [49,79,48,60,100]
midterm_score = [kor_score, math_score, eng_score]
copyed_midterm = midterm_score[:] 으로 하면 2차원부터는 안됨.
복사는 import copy 해서 copy.deepcopy 해야함.
Function and Console I/O
함수. 코드를 논리적인 단위로 분리. 캡술화. 안에 몰라도 인터페이스만 알면 사용 가능 코드는 하나의 보고서, 글이다.
실제 수학 수식처럼 쓸 수 있다.

paramter 유무, 반환 값(return value) 유무에 따라 함수의 형태가 다름
Parameter 없음 | Parameter 존재 | |
반환 값 없음 | 함수 내의 수행문만 수행 | Parameter를 사용, 수행문만 수행 |
반환 값 존재 | parameter없이, 수행문 수행 후 결과값 반환 | Parameter를 사용하여 수행문 수행 수 결과값 반환 |
입력.
print("Enter your name")
somebody = input() 또는 somebody = input("이름을 입력하세요: ")
print("Hi", somebody)
string으로 입력받음.
print("hello", "again!" + str(100), 100)
프린트를 활용해서 형식(format)에 맞춰서 출력
일반적으로 %-format 과 str.format() 함수를 사용함
print('%s %s' % ('one', 'two'))
print('{} {}'.format('one', 'two'))
print('%d %d' % (1, 2))
print('{} {}'.format(1,2))
"%datatype" % (variable) 형태로 출력 양식을 표현
print("I eat %d apples." % 3)
print("I eat %s apples." % "five")
number = 3; day = "three"
print("I ate %d apples. I was sick for %s days." % (number, day))
print("Product: %s, Price per unit: %f." % ("Apple", 5.243))
근데 이러면 Product: Apple, Price per unit: 5.243000. 이 나옴.
그래서 자리수 조정 가능.
print("art: %5d, Price epr Unit: %8.2f" % (453, 59.058))
5, 8 정수부분 -> 이만큼 자리를 차지해주세요
.2 소수부분 -> 소수 밑에 이만큼만 출력해주세요
"~~~~{datatype}~~~~".format(argument)
age = 36; name = 'Sungchul Choi'
print("I ' m {0} years old.".format(age))
print("My name is {0} and {1} years old.".format(name, age))
print("Product: {0}, Price per unit: {1:.3f}.".format("Apple", 5.243))
: 앞에 있는 정수는 순서. : 뒤는 % 로 할때랑 같음.
왼쪽으로 정렬, 오른쪽으로 정렬
print("Product: {0:<10s}, Price per unit: {1:>10.3f}.".format("Apple, 5.243))
해당 표시할 내용을 변수로 표시하여 입력
print("Product: %(name)10s, Price per unit: %(price)10.5f." % {"name":"Apple", "price":5.243}) % 뒤는 딕셔너리 라고 함.
print("Product: {name:>10s}, Price per unit: {price:10.5f}.".format(name="Apple", price=5.243))
요샌 f-string이 대세! python 3.6 이후, PEP498에 근거한 formatting 기법
name = "Minsu"
age = 39
print(f"Hello, {name}. You are {age}.")
print(f"{name:20}")
print(f'{name:>20})
print(f'{name:*<20}') * 로 나머지 빈공간을 채워줘
print(f'{name:*>20}')
print(f'{name:*^20}')
number = 3.141592653589793
print(f'{number:.2f}')
Conditionals and Loops
조건문으로 if, else, elif 등의 예약어를 사용. true false에 따라 어떤걸 할지
a == b. a is b
a != b. a is not b
is 와 is not은 같은 메모리 주소인지 확인하는 연산.
-5 ~ 255까지는 미리 메모리 공간을 선점해서 같은 주소.
a = 100
b = 100
a is b -> True
a = 300
b = 300
a is b -> False
if 1: ... 은 참
if "abc" 는 참. if "" 은 거짓. 존재하면 true. 존재하지 않으면 false.
삼항 연산자 (Ternary operators)
value = 12
is_even = True if value % 2 == 0 else False
is_even
결과값 True
반복문으로 for, while 사용
range(5) -> [0,1,2,3,4]
10진수 -> 2진수
decimal = 10
result = ''
while (demical > 0):
remainder = decimal % 2
decimal = decimal // 2
result = str(remainder) + result
디버깅
문법적 에러
Error 메세지 분석 등 스스로 해결방법 익혀야함
논리적 에러
기대대는 결과값이 나오는지 안나오는지 실험
인터넷에 물어보기
String and advanced function concept
String
정수형.
int 4바이트 -2^31 ~ 2^31 - 1
long 무제한 무제한
실수형.
float 8바이트 2^64. 약 10-308 ~ 10^308
문자열의 각 문자는 개별주소(offset)을 가짐
문자열 함수
함수명 | 기능 |
len(a) | 문자열의 문자 개수를 반환 |
a.upper() | 대문자로 변환 |
a.lower() | 소문자로 변환 |
a.capitalize() | 첫 문자를 대문자로 변환 |
a.title() | 제목 형태로 변환 띄워쓰기 후 첫 글자만 대문자 |
a.count(‘abc’) | 문자열 a에 ‘abc’가 들어간 횟수 반환 |
a.find(‘abc’) a.rfind(‘abc’) |
문자열 a에 ‘abc’가 들어간 위치(오프셋) 반환 |
a.startswith(‘abc’) | 문자열 a는 ‘abc’로 시작하는 문자열여부 반환 |
a.endswith(‘abc’) | 문자열 a는 ‘abc’로 끝나는 문자열 여부 반환 |
a.strip() | 좌우 공백을 없앰 |
a.rstrip() | 오른쪽 공백을 없앰 |
a.lstrip() | 왼쪽 공백을 없앰 |
a.split() | 공백을 기준으로 나눠 리스트로 반환 |
a.split(‘abc’) | abc를 기준으로 나눠 리스트로 반환 |
a.isdigit() | 문자열이 숫자인지 여부 반환 |
a.islower() | 문자열이 소문자인지 여부 반환 |
a.isupper() | 문자열이 대문자인지 여부 반환 |
a.strip() | 좌우 공백을 없앰 |
특수문자
문자 | 설명 |
\ [Enter] | 다음 줄과 연속임을 표현 |
\\ | \ 문자 자체 |
\’ | ‘문자 |
\” | “문자 |
\b | 백 스페이스 |
\n | 줄 바꾸기 |
\t | TAB 키 |
\e | ESC 키 |
앞에 r써서 raw_string쓰면 특수문자 안먹힘.
Function 2
Call by Value
함수에 인자를 넘길 때 값만 넘김.
함수 내에 인자 값 변경 시, 호출자에게 영향을 주지 않음.
Call by Reference
함수에 인자를 넘길 때 메모리 주소를 넘김.
함수 내에 인자 값 변경 시,ㅣ 호출자의 값도 변경됨.
파이썬에선 Call by Object Reference 라는걸 쓴다.
객체의 주소가 함수로 전달되는 방식
def spam(eggs): # 객체의 주소가 넘어감
eggs.append(1) # 아직 같이 가리킴
eggs = [2, 3] # 끊어짐
ham = [0]
spam(ham)
print(ham) # [0, 1]
swap
a = [1,2,3,4,5] 일 때 진짜 바뀐건?
def swap_value (x, y):
temp = x
x = y
y = temp
def swap_offset(offset_x, offset_y):
temp = a[offset_x] # 함수 밖의 것을 가져와서 쓰는거라 의미없음
a[offset_x] = a[offest_y]
a[offset_y] = temp
def swap_reference(a, offset_x, offset_y):
temp = a[offset_x]
a[offset_x] = a[offset_y]
a[offset_y] = temp
swap_offset과 swap_refercence
swap_offset: a 리스트의 전역 변수 값을 직접 변경
swap_reference: a 리스트 객체의 주소 값을 받아 값을 변경
def swap_reference(a, offset_x, offset_y):
templist = a[:] # 새롭게 들어온걸 복사하고 시작
temp = a[offset_x]
a[offset_x] = a[offset_y]
a[offset_y] = temp
Function - Scoping Rule
지역변수(local variable), 전역변수(Global variable)
global 변수 하고싶으면
def f():
global s
s = "I love London!"
print(s)
s = "I love Paris!"
f() # "I love London!"
print(s) # "I love London!"
재귀함수 (recursive Function)
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n-1)
print(factorial(5)) # 5*4*3*2*1 = 120
type hints
dynamic typing. 처음 사용하는 사용자는 interface를 알기 어렵다는 단점.
python 3.5 버전 이후로는 PEP 484에 기반하여 type hints 기능 제공
def do_function(var_name: var_type) -> return_type:
pass
def type_hint_example(name: str) -> str:
return f"Hello, {name}"
docstring
함수에 대한 상세스펙을 자선에 작성 -> 함수 사용자의 이행도 UP
걍 함수 처음에 설명해주는거
함수 작성 가이드 라인
함수는 짧게 여러개를 만든다. (줄 수를 줄일 것)
함수 이름에 역할, 의도를 명확히 들어낼 것
명확하게. 닉값.
함수는 언제만드는가?
공통적으로 사용되는 코드는 함수로 변환
복잡한 수식 -> 식별 가능한 이름의 함수로 변환
복잡한 조건 -> 식별 가능한 이름의 함수로 변환
사람을 위한 코드
팀워크!
사람이 이해할 수 있는 코드를 짜야 한다. 보고서다.
논리적으로 읽기 좋은 코드
규칙 = 코딩 컨벤션
구글 파이썬 컨벤션
읽기 좋은 코드가 좋은 코드
- 들여쓰기 4공백
- 한줄은 79자까지
- 불필요한 공백은 피함
- = 연산자는 1칸 이상 안띄움
- 주석은 항상 갱신, 불필요한 주석은 삭제
- 코드의 마지막에는 항상 한 줄 추가
- 소문자 l, 대문자 O, 대문자 I 금지
- 함수명은 소문자로 구성, 필요하면 밑줄로 나눔
flake8 모듈로 체크 - flake8 <파일명>
conda install -c anaconda flake8
최근에는 black 모듈을 활용하여 pep8 like 수준을 준수
black codename.py 명령을 사용
알아서 고쳐줌
피어세션
오늘 피어세션은 오늘 배웠던 내용 중 중요한 부분, 과제에 관한 조언 등을 주고받고 코딩문제 풀이방법을 공유했다.
기본적인 문법공부지만 String의 formatting 수업이 정말 좋았다고 하였고, 과제는 테스트를 어떻게 하는지, String을 어떻게 다루면 되는지에 관한 정보를 서로 주고받았다.
코딩문제는 매일 leetcode에서 문제 풀기로 했던 https://leetcode.com/explore/challenge/card/january-leetcoding-challenge-2021/581/week-3-january-15th-january-21st/3608/ 문제 풀이를 공유하는 시간을 가졌다.
크게 2가지의 다른 풀이법을 보였다.
첫번째 풀이: 포인터
from typing import List
class Solution:
def maxOperations(self, nums: List[int], k: int) -> int:
nums.sort()
# print(nums, k)
lp = 0
rp = len(nums)-1
count = 0
while lp < rp:
tsum = nums[lp] + nums[rp]
if tsum > k:
rp -= 1
elif tsum < k:
lp += 1
else:
count += 1
rp -= 1
lp += 1
return count
print(Solution.maxOperations(Solution,[1,2,3,4],5),2)
print(Solution.maxOperations(Solution,[3,1,3,4,3],6),1)
리스트를 오름차순으로 정렬
맨 왼쪽, 맨 오른쪽 각각 포인터 하나씩.
왼쪽포인터 < 오른쪽 포인터 일때까지 반복하는데:
두 포인터가 가리키는 숫자의 합이:
k 보다 클 경우: 오른쪽 포인터를 왼쪽으로 이동시킨다.
k 보다 작을 경우: 왼쪽 포인터를 오른쪽으로 이동시킨다.
k 와 같을 경우: 카운터를 증가시키고 왼쪽포인터를 오른쪽으로, 오른쪽 포인터를 왼쪽으로 이동시킨다. 문제에서 두 숫자 모두 제외시키기 때문.
반복문이 끝나고 나온 카운터가 정답.
두번째 풀이: 카운터
from collections import Counter
class Solution:
def maxOperations(self, nums: List[int], k: int) -> int:
nums=Counter(nums)
answer=0
for i in [k-i for i in nums if k-i<=k//2]:
if i != k-i:
answer += min(nums.get(i,0), nums.get(k-i,0))
else:
answer += nums.get(i,0)//2
return answer
리스트가 [1,1,1,2,3,4,5,5,6], k가 6일 경우
1이 3개, 2가 1개, 3이 1개, 4가 1개, 5가 2개, 6이 1개이다.
1의 경우 5가 있으면 조건을 만족한다. 하지만 1이 3개나 있지만 5가 2개밖에 없으므로 2개만 만들 수 있다. 그래서 둘 중 최소값 min을 사용한다.
이렇게 구한 정답을 반환한다.
포인터의 경우 값이 중복된 만큼 더 순회를 해야하지만 카운터의 경우 그럴 필요가 없다.
사람들 생각은 다 비슷할 줄 알았는데 역시 배웠다.
후기
할게 많고 어제도 잠에 늦게들어서 피곤하다. 오늘수업은 정말 인터넷 검색해도 이상하거나 잘 안나오지만 꼭 알아야 하는 것들을 한번에 다 본 느낌이라 정말 좋고 많이 배웠다. 이런 교육에 감사하다.
'과거의 것들 > AI Tech boostcamp' 카테고리의 다른 글
AITech 학습정리-[DAY 6] Numpy / 벡터 / 행렬 (0) | 2021.11.26 |
---|---|
AITech 학습정리-[DAY 5] 파이썬으로 데이터 다루기 (0) | 2021.11.26 |
AITech 학습정리-[DAY 3] 파이썬 기초 문법 II (0) | 2021.11.26 |
AITech 학습정리-[DAY 1] 파이썬/AI 개발환경 준비하기 (0) | 2021.11.26 |
앞으로 올리는거는 과거의 것을 복사하는 것임 (0) | 2021.11.26 |