python 2.x 버전은 2020년 1월 1일부터 더이상 지원되지 않는다.
# 버전확인
import sys
print(sys.version_info)
sys.version_info(major=3, minor=7, micro=12, releaselevel='final', serial=0)
print(sys.version)
3.7.12 (default, Nov 4 2022, 00:01:41)
[Clang 13.1.6 (clang-1316.0.21.2.5)]
Python 3.6+ 버전부터는 FastAPI 를 제공한다.
https://fastapi.tiangolo.com/ko/
Python 3.8 버전부터는 대입식을 제공한다.
https://docs.python.org/ko/3/whatsnew/3.8.html
Python 3.11 버전에서는 이전버전 3.10 에 비해 10~60% 속도향상에 힘쓰고 있다.
https://docs.python.org/3/whatsnew/3.11.html
class A():
def a_a():
print("a_a")
def a_b():
print("a_b")
def a():
print("a")
def b():
print("b")
sample_dict: {
key1: value1,
key2: value2,
key3: value3,
}
a = 1
name: str = "Lucas"
age: int = 29
이외에 라인 길이는 79개 문자, 들여쓰기는 스페이스바 4번의 규칙이 있는데 저는 사실상 라인 150자 까지도 사용하기도 하고, 스페이스바 보다는 tab으로 들여쓰기를 주로 합니다.
해당 부분은 사람마다 다르게 편리한데로 사용하는 것 같습니다.
저는 black 라이브러리를 사용하여 편리하게 라인을 정리함.
black: https://pypi.org/project/black/
[GOOD]
if a is not b:
~~~~
[BAD]
if not a is b:
~~~~
empty_value = ""
[GOOD]
if not empty_value:
print("빈값")
[BAD]
if len(empty_value) == 0:
print("빈값")
text_value = "Hi"
[GOOD]
if text_value:
print(text_value)
[BAD]
if len(text_value) != 0:
print(text_value)
value = 3
answer = "짝수" if value % 2 == 0 else "홀수"
print(answer)
num_list = [1, 2, 3, 4, 5]
new_num_list = [num * 2 for num in num_list]
print(new_num_list)
num, num_value, arr_list, dict_value, tuple_value = 0, "", [], {}, ()
if (
num // 2 is 0
and not num_value
and not arr_list
and not dict_value
and not tuple_value
):
print("")
else:
print("")
저는 isort 라이브러리를 사용하여 편리하게 import 구문을 정리함.
isort: https://pypi.org/project/isort/
PEP8 원문: https://peps.python.org/pep-0008/
PEP8 번역: https://wikidocs.net/7896
bytes 와 str 은 같은 문자열 처럼 보이지만 bytes 는 앞에 b"문자열" 이런식으로 앞에 'b' 를 붙혀서 bytes 로 표시한다
bytes 로 된 문자열을 처리할때는 아래와 같이 decode("utf-8") 를 이용해서 str 형태로 만들거나,
파일 읽기/쓰기 할때는 'w', 'r' 옵션에서 'b' 를 추가해서 'wb', 'rb' 옵션을 준다
bytes -> str 로 변환
def to_str(bytes_or_str):
if isinstance(bytes_or_str, bytes):
return bytes_or_str.decode("utf-8")
return bytes_or_str
print(to_str(b"foo"))
print(to_str("bar"))
print(to_str(b"\xed\x95\x9c"))
str -> bytes 로 변환
def to_bytes(bytes_or_str):
if isinstance(bytes_or_str, str):
return bytes_or_str.encode("utf-8")
return bytes_or_str
print(to_bytes(b"foo"))
print(to_bytes("bar"))
print(to_bytes("한글"))
바이트 파일 쓰기
with open("data.bin", "wb") as f:
f.write(b'\xed\x95\x9c\xea\xb8\x80')
바이트 파일 읽기
with open("data.bin", "rb") as f:
print(f.read())
현재 Python encoding 확인
import locale
print(locale.getpreferredencoding())
Python 에서도 C 처럼 출력할 떄 format 을 이용해서 숫자, 문자 등을 표시할 수 있다
하지만 C 스타일은 %d, %i, %s 등 사용시 휴먼에러 발생할 가능성도 크고 가독성이 떨어진다
그래서 저는 무조건적으로 f-string 을 사용한다
text = "글자"
num = 123
float_num = 123.4567
places = 3
print("format 활용 text: {0}, num: {1}, float_num: {2}, places_float_num: {3:.{4}f}".format(text, num, float_num, float_num, places))
print("format 활용 text: {}, num: {}, float_num: {}, places_float_num: {:.{}f}".format(text, num, float_num, float_num, places))
print(f"f-string 활용 text: {text}, num: {num}, float_num: {float_num}, places_float_num{float_num:.{places}f}")
from urllib.parse import parse_qs
my_values = parse_qs("빨강=5&파랑=0&초록=", keep_blank_values=True)
print(my_values)
# .get 함수를 사용할 때 값이 없으면 자동으로 None 값으로 출력
print(f'빨강: {my_values.get("빨강")}')
print(f'초록: {my_values.get("초록")}')
print(f'투명도: {my_values.get("투명도")}')
# .get 함수 사용 후 None, 0 인 경우 False 로 취급돼서 or 연산자에 의해서 0 으로 출력
red = my_values.get("빨강", [""])[0] or 0
green = my_values.get("초록", [""])[0] or 0
opacity = my_values.get("투명도", [""])[0] or 0
print(f'빨강: {red}')
print(f'초록: {green}')
print(f'투명도: {opacity}')
# 식을 간결하게 쓰기
red_str = my_values.get("빨강", [""])
red = int(red_str[0]) if red_str[0] else 0
print(f'red: {red}')
# 식을 명확하게 쓰기
green_str = my_values.get("초록", [""])
if green_str[0]:
green = int(green_str[0])
else:
green = 0
print(f'green: {green}')
# 도우미 함수를 이용하여 간결하고 명확하게 쓰기
def get_first_int(values, key, defalut=0):
found = values.get(key, [""])
if found[0]:
return int(found[0])
return defalut
print(f'빨강: {get_first_int(my_values, "빨강")}')
print(f'초록: {get_first_int(my_values, "초록")}')
print(f'투명도: {get_first_int(my_values, "투명도")}')
favorite_snacks = {
"짭조름한 과자": ("프레즐", 100),
"달콤한 과자": ("쿠키", 180),
"채소": ("당근", 20),
}
# 언패킹 하여 변수에 바로 대입
print(f"favorite_snacks.items() => {favorite_snacks.items()}")
(
((type1), (name1, cals1)),
((type2), (name2, cals2)),
((type3), (name3, cals3)),
) = favorite_snacks.items()
print(f"제일 좋아하는 {type1} 는 {name1}, {cals1} 칼로리입니다.")
print(f"제일 좋아하는 {type2} 는 {name2}, {cals2} 칼로리입니다.")
print(f"제일 좋아하는 {type3} 는 {name3}, {cals3} 칼로리입니다.")
# 버블정렬
def bubble_sort(names):
for _ in range(len(names)):
print("-----")
for i in range(1, len(names)):
if names[i] < names[i - 1]:
temp = names[i]
names[i] = names[i - 1]
names[i - 1] = temp
print(names)
names = ["프레즐", "당근", "쑥갓", "베이컨"]
print("\n버블정렬")
bubble_sort(names)
print(names)
# 언패킹을 사용한 버블정렬
def bubble_sort(names):
for _ in range(len(names)):
print("-----")
for i in range(1, len(names)):
if names[i] < names[i - 1]:
names[i - 1], names[i] = names[i], names[i - 1]
print(names)
names = ["프레즐", "당근", "쑥갓", "베이컨"]
print("\n언패킹을 사용한 버블정렬")
bubble_sort(names)
print(names)
# enumrate 와 언패킹 활용
snaks = [("베이컨", 350), ("도넛", 240), ("머핀", 190)]
for idx, (name, cal) in enumerate(snaks, 1):
print(f"#{idx}: {name}은 {cal} 칼로리 입니다.")
개인적으로 for 문을 사용할 때는 range 사용을 최소화하는게 좋다
# 파이썬 반복문 사용
flavor_list = ["바닐라", "딸기", "초코"]
for flavor in flavor_list:
print(f'{flavor}맛')
# range 사용
for i in range(len(flavor_list)):
print(f'{i + 1}: {flavor_list[i]}')
# enumrate 사용
flavor = enumerate(flavor_list)
print(next(flavor))
print(next(flavor))
print(next(flavor))
# print(next(flavor)) # 4 번째 값은 없어서 StopIteration 에러 출력
# enumerate 두번째 인자값으로 수를 세기 시작하는 값 지정
for idx, flavor in enumerate(flavor_list, 1):
print(f"{idx}: {flavor}")
zip 을 사용해서 이터레이터를 합칠수 있다
합친 이터레이터 값의 개수가 다른경우 itertools.zip_longest 를 활용하여 빈값을 채워준다
import itertools
names = ["Lucas", "이진수"]
name_len = [len(name) for name in names]
names.append("abcdefg")
# itertools.zip_longest 에서 fillvalue 파라미터를 이용해서 빈값을 특정 값으로 치환해줄수 있다 defalut 는 None 이다.
for name, name_len in itertools.zip_longest(names, name_len, fillvalue="null"):
print(f'{name}: {name_len}')
파이썬을 공부하면서 아래와 같이 작성하는 구절은 본적이 없다
그만큼 while 문이나 for 문 뒤에 else 는 절대적으로 사용하지 않는다.
while False:
print("실행되지 않는 줄")
else:
print("While else block")
a = 4
b = 9
for i in range(2, min(a, b) + 1):
print(f"검사중: {i}")
if a % i == 0 and b % i == 0:
print("서로수 아님")
break
else:
print("서로수")
# 도우미 함수를 활용하자
def coprime(a, b):
for i in range(2, min(a, b) + 1):
if a % i == 0 and b % i == 0:
return False
return True
print(coprime(4, 9))
대입식을 사용하면 코드의 가독성이 좋아지고 줄수고 짧아진다
그러나 아직 익숙하지 않다
fresh_fruit = {
"사과": 10,
"바나나": 8,
"레몬": 5,
}
count = fresh_fruit.get("레몬", 0)
if count >= 4:
print("make lemonade")
else:
print("no fruit")
# 대입식 사용
# vscode python 3.8 이하 버전에서 사용 시 에러 발생
# Operator ":=" requires Python 3.8 or newer
# File "/Users/dlwlstn/soomgo_git/test/t1.py", line 16
# if count := fresh_fruit.get("레몬", 0):
# ^
# SyntaxError: invalid syntax
# 파이썬 3.8 부터 사용가능
if (count := fresh_fruit.get("레몬", 0)) >= 4:
print("make lemonade")
else:
print("no fruit")
요악 및 느낌점
파이썬 2.x 버전은 더이상 사용하지 않고, 3.x 버전을 사용한다
이것 또한 개인적으로 실무하면서 느낀점은 최소 3.7 이상 버전을 사용하는 것이 좋을 것 같다
black, isort 라이브러리를 사용하여 코드를 관리하면 편리하다
또한 무조건 문자열 포멧팅을 f-string 을 사용하고, enumrate, zip 등 내장함수를 활용하면 코드 퀄리티가 높아진다.
3.8 이후부터 나온 대입식은 아직 생소하기도 하지만 유용하게 사용가능하다
파이썬은 쉽고 빠르게 배울 수 있고, 내장함수가 기능의 퀄리티가 좋고 많은 라이브러리가 있다