๐ ํ์ด์ฌ 3.9/3.10/3.11์ ์๋ก์ด ๊ธฐ๋ฅ ํ์ ๐

์๋ ํ์ธ์, ํ์ด์ฌ ๋ํ ์ฌ๋ฌ๋ถ! ์ค๋์ ํ์ด์ฌ์ ์ต์ ๋ฒ์ ๋ค์ ๋ํด ๊น์ด ํํค์ณ๋ณผ ๊ฑฐ์์. 3.9๋ถํฐ 3.11๊น์ง, ํ์ด์ฌ์ด ์ด๋ป๊ฒ ์งํํ๋์ง ํจ๊ป ์์๋ณด์ฃ . ์ฌ๋ฅ๋ท์์ ํ๋ก๊ทธ๋๋ฐ ์ค๋ ฅ์ ๋ฝ๋ด๊ณ ์ถ์ ๋ถ๋ค์ด๋ผ๋ฉด ์ฃผ๋ชฉ! ์ด ๊ธ์ ์ฝ๊ณ ๋๋ฉด ์ฌ๋ฌ๋ถ๋ ํ์ด์ฌ ๊ณ ์๊ฐ ๋ ์ ์์ ๊ฑฐ์์. ใ ใ ใ
๐ก Tip: ํ์ด์ฌ์ ์๋ก์ด ๊ธฐ๋ฅ๋ค์ ์ตํ๋ฉด, ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ๋ถ์ ์ฝ๋ฉ ์ค๋ ฅ์ ๋์ฑ ๋น๋๊ฒ ๋ฝ๋ผ ์ ์์ด์!
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ์์ํด๋ณผ๊น์? ํ์ด์ฌ์ ์ธ๊ณ๋ก ํ๋ฉ ๋น ์ ธ๋ด ์๋ค! ๐โโ๏ธ
๐ Python 3.9์ ์๋ก์ด ๊ธฐ๋ฅ๋ค
2020๋ 10์์ ์ถ์๋ ํ์ด์ฌ 3.9๋ ์ ๋ง ๋ง์ ๊ฐ์ ์ฌํญ๊ณผ ์๋ก์ด ๊ธฐ๋ฅ๋ค์ ๊ฐ์ ธ์์ด์. ๋ง์น ํฌ๋ฆฌ์ค๋ง์ค ์ ๋ฌผ์ ํธ๋ ๊ฒ์ฒ๋ผ ์ค๋ ๋ ๋ง์์ผ๋ก ํ๋์ฉ ์ดํด๋ณผ๊น์?
1. ๋์ ๋๋ฆฌ ๋ณํฉ ๋ฐ ์ ๋ฐ์ดํธ ์ฐ์ฐ์ (|, |=)
์ด์ ๋์
๋๋ฆฌ๋ฅผ ํฉ์น ๋ ๋ ์ด์ update()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ง ์์๋ ๋ผ์. ํ์ด์ฌ 3.9์์๋ ํ์ดํ(|) ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด์ ๋์
๋๋ฆฌ๋ฅผ ์ฝ๊ฒ ๋ณํฉํ ์ ์๊ฒ ๋์ด์.
# ์ด์ ๋ฐฉ์
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
merged = {**dict1, **dict2}
# ์๋ก์ด ๋ฐฉ์
merged = dict1 | dict2
์ด๋์? ํจ์ฌ ๊ฐ๋จํด ๋ณด์ด์ฃ ? ใ ใ ใ ์ด์ ๋์ ๋๋ฆฌ ๋ณํฉ์ด ๋ง์น ๋ ๊ฐ๋ฌผ์ด ๋ง๋๋ ๊ฒ์ฒ๋ผ ์์ฐ์ค๋ฌ์์ก์ด์! ๐
๐จ ์ฃผ์: ๋ ๋์ ๋๋ฆฌ์ ๊ฐ์ ํค๊ฐ ์๋ค๋ฉด, ์ค๋ฅธ์ชฝ ๋์ ๋๋ฆฌ์ ๊ฐ์ด ์ฐ์ ์์๋ฅผ ๊ฐ์ ธ์. ๋ง์น ๊ฐ์๋ฐ์๋ณด์์ ํญ์ ์ค๋ฅธ์์ด ์ด๊ธฐ๋ ๊ฒ์ฒ๋ผ์!
2. ๋ฌธ์์ด ๋ฉ์๋์ ์๋ก์ด ๊ธฐ๋ฅ: removeprefix()์ removesuffix()
๋ฌธ์์ด ๋ค๋ฃจ๋ ๊ฒ ์ด์ ๋ ์ฌ์์ก์ด์! removeprefix()
์ removesuffix()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฌธ์์ด์ ์๋ถ๋ถ์ด๋ ๋ท๋ถ๋ถ์ ์์ฝ๊ฒ ์ ๊ฑฐํ ์ ์์ฃ .
text = "Hello, World!"
print(text.removeprefix("Hello, ")) # ์ถ๋ ฅ: World!
print(text.removesuffix("!")) # ์ถ๋ ฅ: Hello, World
์ด ๊ธฐ๋ฅ๋ค ๋๋ถ์ ๋ฌธ์์ด ์ฒ๋ฆฌ๊ฐ ํจ์ฌ ๊ฐํธํด์ก์ด์. ๋ง์น ์ผ์ดํฌ์ ์ฅ์์ ๋ผ์ด๋ด๋ ๊ฒ์ฒ๋ผ ์ฝ์ฃ ? ๐ฐ
3. ํ์ ํํธ์ ๊ฐ์
ํ์ด์ฌ 3.9์์๋ ํ์
ํํธ๋ฅผ ๋์ฑ ๊ฐ๊ฒฐํ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ๋์ด์. ์ด์ typing
๋ชจ๋์ importํ์ง ์๊ณ ๋ ๋ด์ฅ ์ปฌ๋ ์
ํ์
์ ์ง์ ์ฌ์ฉํ ์ ์์ด์.
# ์ด์ ๋ฐฉ์
from typing import List, Dict
def process_items(items: List[str]) -> Dict[str, int]:
...
# ์๋ก์ด ๋ฐฉ์
def process_items(items: list[str]) -> dict[str, int]:
...
์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋๊ฐ ๋ ๊น๋ํด์ง๊ณ , ๊ฐ๋ ์ฑ๋ ์ข์์ง์ฃ . ๋ง์น ๋ณต์กํ ์์์ ๊ฐ๋จํ๊ฒ ์ ๋ฆฌํ ๊ฒ ๊ฐ์์! ๐จโ๐ซ
4. ์๋ก์ด ํ์
ํ์ด์ฌ 3.9์์๋ ์๋ก์ด ํ์(PEG ํ์)๋ฅผ ๋์ ํ์ด์. ์ด ํ์๋ ์ด์ ์ LL(1) ํ์๋ณด๋ค ๋ ์ ์ฐํ๊ณ ๊ฐ๋ ฅํด์. ๋๋ถ์ ๋ฌธ๋ฒ์ ๋ชจํธ์ฑ์ ๋ ์ ์ฒ๋ฆฌํ ์ ์๊ฒ ๋์ฃ .
์ด ๋ณํ๋ ์ผ๋ฐ ์ฌ์ฉ์๋ค์๊ฒ๋ ํฌ๊ฒ ์๋ฟ์ง ์์ ์ ์์ง๋ง, ์ธ์ด ๊ฐ๋ฐ์๋ค์๊ฒ๋ ์ ๋ง ํฐ ๋ณํ์์. ๋ง์น ์๋์ฐจ์ ์์ง์ ์์ ํ ์๊ฒ์ผ๋ก ๋ฐ๊พผ ๊ฒ๊ณผ ๊ฐ์ฃ ! ๐๐จ
5. ์๊ฐ ์ธก์ ํจ์์ ๊ฐ์
time.monotonic()
๊ณผ time.perf_counter()
ํจ์๊ฐ ์ด์ ๋๋
ธ์ด ๋จ์์ ์ ๋ฐ๋๋ฅผ ์ ๊ณตํด์. ์ด์ ์๋ ๋ง์ดํฌ๋ก์ด๊น์ง๋ง ์ง์ํ๋๋ฐ, ์ด์ ๋ ๋ ์ ๋ฐํ ์๊ฐ ์ธก์ ์ด ๊ฐ๋ฅํด์ก์ด์.
import time
start = time.perf_counter_ns()
# ์๊ฐ์ ์ธก์ ํ๊ณ ์ถ์ ์ฝ๋
end = time.perf_counter_ns()
print(f"์คํ ์๊ฐ: {end - start} ๋๋
ธ์ด")
์ด์ ์ฌ๋ฌ๋ถ์ ์ฝ๋๊ฐ ์ผ๋ง๋ ๋น ๋ฅธ์ง ๋ ์ ํํ๊ฒ ์ ์ ์์ด์. ๋ง์น ์ก์ ์ ์์ ๊ธฐ๋ก์ 1000๋ถ์ 1์ด๊น์ง ์ธก์ ํ๋ ๊ฒ์ฒ๋ผ ์ ๋ฐํ์ฃ ! ๐โโ๏ธโฑ๏ธ
6. zoneinfo ๋ชจ๋ ์ถ๊ฐ
์๊ฐ๋ ์ฒ๋ฆฌ๊ฐ ๋ ์ฌ์์ก์ด์! zoneinfo
๋ชจ๋์ด ์ถ๊ฐ๋์ด IANA ์๊ฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ๋์ฃ .
from zoneinfo import ZoneInfo
from datetime import datetime
# ์์ธ ์๊ฐ
seoul_time = datetime.now(ZoneInfo("Asia/Seoul"))
print(f"์์ธ ์๊ฐ: {seoul_time}")
# ๋ด์ ์๊ฐ
ny_time = datetime.now(ZoneInfo("America/New_York"))
print(f"๋ด์ ์๊ฐ: {ny_time}")
์ด์ ์ ์ธ๊ณ ์๊ฐ์ ๋ค๋ฃจ๋ ๊ฒ ํจ์ฌ ์ฌ์์ก์ด์. ๋ง์น ์ธ๊ณ ์๊ณ๋ฅผ ์๋ชฉ์ ์ฐจ๊ณ ๋ค๋๋ ๊ฒ ๊ฐ์ฃ ? ๐โ
7. ์ผ๋ฐ ํํ์
ํ์ด์ฌ 3.9์์๋ ์ผ๋ฐ ํํ์(Generic Expression)์ด๋ผ๋ ์๋ก์ด ๊ฐ๋ ์ด ๋์ ๋์ด์. ์ด๋ฅผ ํตํด ํ์ ํํธ๋ฅผ ๋์ฑ ์ ์ฐํ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ๋์ฃ .
from typing import Generic, TypeVar
T = TypeVar('T')
class Stack(Generic[T]):
def __init__(self):
self.items: list[T] = []
def push(self, item: T) -> None:
self.items.append(item)
def pop(self) -> T:
return self.items.pop()
# ๋ฌธ์์ด ์คํ
string_stack = Stack[str]()
string_stack.push("Hello")
string_stack.push("World")
# ์ ์ ์คํ
int_stack = Stack[int]()
int_stack.push(1)
int_stack.push(2)
์ด๋ ๊ฒ ํ๋ฉด ๋ค์ํ ํ์ ์ ์คํ์ ์ฝ๊ฒ ๋ง๋ค ์ ์์ด์. ๋ง์น ๋ ๊ณ ๋ธ๋ก์ฒ๋ผ ์ํ๋ ๋๋ก ์กฐ๋ฆฝํ ์ ์์ฃ ! ๐งฑ
8. ๋ฉํฐํ๋ก์ธ์ฑ ๊ฐ์
ํ์ด์ฌ 3.9์์๋ ๋ฉํฐํ๋ก์ธ์ฑ ๋ชจ๋์ด ๊ฐ์ ๋์์ด์. ํนํ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ด ๋ ํจ์จ์ ์ผ๋ก ๋ณ๊ฒฝ๋์ฃ .
from multiprocessing import shared_memory
# ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์์ฑ
shm = shared_memory.SharedMemory(create=True, size=10)
# ๊ณต์ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ดํฐ ์ฐ๊ธฐ
shm.buf[:] = b'Hello'
# ๋ค๋ฅธ ํ๋ก์ธ์ค์์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ
existing_shm = shared_memory.SharedMemory(name=shm.name)
print(bytes(existing_shm.buf[:5])) # ์ถ๋ ฅ: b'Hello'
# ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ํด์
shm.close()
shm.unlink()
์ด์ ์ฌ๋ฌ ํ๋ก์ธ์ค ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ ํจ์จ์ ์ผ๋ก ๊ณต์ ํ ์ ์์ด์. ๋ง์น ์ฌ๋ฌ ์ฌ๋์ด ํ๋์ ์น ํ์ ๊ณต์ ํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ ! ๐ฅ๐๏ธ
๐ก Tip: ์ฌ๋ฅ๋ท์์ ํ์ด์ฌ 3.9์ ์๋ก์ด ๊ธฐ๋ฅ๋ค์ ํ์ฉํ ํ๋ก์ ํธ๋ฅผ ๊ณต์ ํด๋ณด์ธ์. ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค์ ๊ด์ฌ์ ๋ ์ ์์ ๊ฑฐ์์!
ํ์ด์ฌ 3.9์ ์๋ก์ด ๊ธฐ๋ฅ๋ค, ์ด๋ ์ ๊ฐ์? ์ ๋ง ๋ง์ ๊ฐ์ ์ฌํญ๋ค์ด ์์ฃ ? ์ด์ 3.10์ผ๋ก ๋์ด๊ฐ๋ณผ๊น์? ๋ ํฅ๋ฏธ์ง์งํ ๊ธฐ๋ฅ๋ค์ด ๊ธฐ๋ค๋ฆฌ๊ณ ์์ด์! ๐ข
๐ Python 3.10์ ์๋ก์ด ๊ธฐ๋ฅ๋ค
2021๋ 10์์ ์ถ์๋ ํ์ด์ฌ 3.10์ ์ ๋ง ๋ง์ ๊ธฐ๋๋ฅผ ๋ฐ์์ด์. ๊ทธ๋งํผ ์๋กญ๊ณ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ๋ค์ด ์ถ๊ฐ๋๊ฑฐ๋ ์. ๋ง์น ๊ธฐ๋ค๋ฆฌ๊ณ ๊ธฐ๋ค๋ฆฌ๋ ์ํ์ ์ํธ์ ๋ณด๋ ๊ฒ์ฒ๋ผ ์ค๋ ๋ ๋ง์์ผ๋ก ์ดํด๋ณผ๊น์? ๐ฟ
1. ๊ตฌ์กฐ์ ํจํด ๋งค์นญ (Structural Pattern Matching)
ํ์ด์ฌ 3.10์ ๊ฐ์ฅ ํฐ ๋ณํ๋ ๋ฐ๋ก ๊ตฌ์กฐ์ ํจํด ๋งค์นญ์ด์์. ์ด ๊ธฐ๋ฅ์ ๋ค๋ฅธ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ switch-case ๋ฌธ๊ณผ ๋น์ทํ์ง๋ง, ํจ์ฌ ๋ ๊ฐ๋ ฅํ๊ณ ์ ์ฐํด์.
def analyze_type(data):
match data:
case []:
print("๋น ๋ฆฌ์คํธ์
๋๋ค.")
case [x]:
print(f"ํ๋์ ์์ {x}๋ฅผ ๊ฐ์ง ๋ฆฌ์คํธ์
๋๋ค.")
case [x, y]:
print(f"๋ ๊ฐ์ ์์ {x}์ {y}๋ฅผ ๊ฐ์ง ๋ฆฌ์คํธ์
๋๋ค.")
case [x, y, *rest]:
print(f"์ฒซ ๋ ์์๋ {x}์ {y}์ด๊ณ , ๋๋จธ์ง๋ {rest}์
๋๋ค.")
case {'name': name, 'age': age}:
print(f"{name}์(๋) {age}์ด์
๋๋ค.")
case _:
print("์ ์ ์๋ ๋ฐ์ดํฐ ํ์์
๋๋ค.")
analyze_type([1, 2, 3, 4, 5])
analyze_type({'name': 'ํ์ด์ฌ', 'age': 30})
์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ๋ณต์กํ if-elif ๊ตฌ๋ฌธ์ ํจ์ฌ ๋ ๊ฐ๊ฒฐํ๊ณ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋ค ์ ์์ด์. ๋ง์น ํผ์ฆ ์กฐ๊ฐ์ ๋ง์ถ๋ ๊ฒ์ฒ๋ผ ๋ฐ์ดํฐ์ ๊ตฌ์กฐ๋ฅผ ํ์ ํ๊ณ ์ฒ๋ฆฌํ ์ ์์ฃ ! ๐งฉ
๐ ๊ฟํ: ๊ตฌ์กฐ์ ํจํด ๋งค์นญ์ ์ฌ์ฉํ๋ฉด ์ฝ๋์ ๊ฐ๋ ์ฑ์ด ํฌ๊ฒ ํฅ์๋ผ์. ํนํ ๋ณต์กํ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๋ค๋ฃฐ ๋ ์ง๊ฐ๋ฅผ ๋ฐํํ์ฃ !
2. ๋ ์ ํํ ์ค๋ฅ ๋ฉ์์ง
ํ์ด์ฌ 3.10์์๋ ์ค๋ฅ ๋ฉ์์ง๊ฐ ๋์ฑ ์์ธํด์ง๊ณ ์ ํํด์ก์ด์. ํนํ ๊ตฌ๋ฌธ ์ค๋ฅ(SyntaxError)์ ๋ํ ๋ฉ์์ง๊ฐ ํฌ๊ฒ ๊ฐ์ ๋์ฃ .
# ํ์ด์ฌ 3.9 ์ด์
if True
print("Hello")
# SyntaxError: invalid syntax
# ํ์ด์ฌ 3.10
if True
print("Hello")
# SyntaxError: expected ':'
์ด์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋ ๋ ์ ํํ ์ด๋๊ฐ ์๋ชป๋๋์ง ์๋ ค์ค์. ๋ง์น ์น์ ํ ์ ์๋์ด ์์ ๋ฅผ ๋ด์ฃผ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ ! ๐จโ๐ซโ
3. ์๋ก์ด ํ์ ์ ๋์จ ์ฐ์ฐ์ (|)
ํ์ ํํธ๋ฅผ ์ฌ์ฉํ ๋, ์ฌ๋ฌ ํ์ ์ ํํํ๊ธฐ ์ํด ์ด์ ํ์ดํ(|) ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ์ ์์ด์.
def greet(name: str | None) -> str:
if name is None:
return "Hello, Guest!"
return f"Hello, {name}!"
print(greet("Alice")) # ์ถ๋ ฅ: Hello, Alice!
print(greet(None)) # ์ถ๋ ฅ: Hello, Guest!
์ด์ ์๋ Union[str, None]
๊ณผ ๊ฐ์ด ์จ์ผ ํ๋๋ฐ, ์ด์ ๋ ํจ์ฌ ๊ฐ๋จํด์ก์ด์. ๋ง์น ํ์ดํํ ๋ ์จ์ ๋ ์ฌ์ด๋ ๋๋ ๊ฒ ๊ฐ์ฃ ? ๐ฎโ๐จ
4. ์ปจํ ์คํธ ๋งค๋์ ์์์ ๊ดํธ ์๋ต
์ด์ ์ฌ๋ฌ ๊ฐ์ ์ปจํ ์คํธ ๋งค๋์ ๋ฅผ ์ฌ์ฉํ ๋ ๊ดํธ๋ฅผ ์๋ตํ ์ ์์ด์.
# ์ด์ ๋ฐฉ์
with (open('file1.txt', 'r') as f1,
open('file2.txt', 'w') as f2):
f2.write(f1.read())
# ์๋ก์ด ๋ฐฉ์
with open('file1.txt', 'r') as f1, \
open('file2.txt', 'w') as f2:
f2.write(f1.read())
์ฝ๋๊ฐ ๋ ๊น๋ํด ๋ณด์ด์ฃ ? ๋ง์น ๋ถํ์ํ ์ฅ์์ ๋ผ์ด๋ธ ๊ฒ ๊ฐ์์. ์ฌํ์ด์ฆ ๋ ๋ฒ ์คํธ! ๐
5. ๋ ๊ฐ๋ ฅํด์ง ํ์ ์ฒดํฌ
ํ์ด์ฌ 3.10์์๋ ํ์ ์ฒดํฌ ๊ธฐ๋ฅ์ด ๋์ฑ ๊ฐํ๋์ด์. ํนํ ์ ๋ค๋ฆญ ํ์ ์ ๋ํ ์ง์์ด ๊ฐ์ ๋์ฃ .
from typing import Generic, TypeVar
T = TypeVar('T')
class Box(Generic[T]):
def __init__(self, content: T):
self.content = content
def get_content(self) -> T:
return self.content
int_box: Box[int] = Box(42)
str_box: Box[str] = Box("Hello")
print(int_box.get_content()) # ์ถ๋ ฅ: 42
print(str_box.get_content()) # ์ถ๋ ฅ: Hello
์ด์ ํ์ ํํธ๋ฅผ ๋ ์ ํํ๊ฒ ์ฌ์ฉํ ์ ์์ด์. ๋ง์น ๋ ๊ณ ๋ธ๋ก์ ๋ชจ์์ ๋ ์ ํํ๊ฒ ๋ง์ถ ์ ์๊ฒ ๋ ๊ฒ ๊ฐ์ฃ ? ๐งฑโจ
6. ์๋ก์ด ํ๋ผ๋ฏธํฐ ์ฌ์ ๋ฌธ๋ฒ
ํจ์์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ์ํ ๋ ์๋ก์ด ๋ฌธ๋ฒ์ ์ฌ์ฉํ ์ ์๊ฒ ๋์ด์.
def greet(name, /, *, greeting="Hello"):
return f"{greeting}, {name}!"
print(greet("Alice", greeting="Hi")) # ์ถ๋ ฅ: Hi, Alice!
print(greet("Bob")) # ์ถ๋ ฅ: Hello, Bob!
# print(greet(name="Charlie")) # ์ค๋ฅ: ์์น ์ ์ฉ ์ธ์์ ํค์๋๋ฅผ ์ฌ์ฉํ ์ ์์
์ฌ๊ธฐ์ /
๋ ๊ทธ ์์ ํ๋ผ๋ฏธํฐ๊ฐ ์์น ์ ์ฉ ์ธ์์์, *
๋ ๊ทธ ๋ค์ ํ๋ผ๋ฏธํฐ๊ฐ ํค์๋ ์ ์ฉ ์ธ์์์ ๋ํ๋ด์. ์ด๋ ๊ฒ ํ๋ฉด ํจ์ ํธ์ถ ๋ฐฉ์์ ๋ ์๊ฒฉํ๊ฒ ์ ์ดํ ์ ์์ฃ . ๋ง์น ํํฐ์์ ๋๋ ์ค ์ฝ๋๋ฅผ ์ ํ๋ ๊ฒ์ฒ๋ผ์! ๐๐ด๏ธ
7. zip() ํจ์์ ๊ฐ์
zip()
ํจ์์ ์๋ก์ด strict
ํ๋ผ๋ฏธํฐ๊ฐ ์ถ๊ฐ๋์ด์. ์ด๋ฅผ ํตํด ๊ธธ์ด๊ฐ ๋ค๋ฅธ ์ดํฐ๋ฌ๋ธ์ zipํ ๋ ์ค๋ฅ๋ฅผ ๋ฐ์์ํฌ ์ ์๊ฒ ๋์ฃ .
numbers = [1, 2, 3]
letters = ['a', 'b', 'c', 'd']
# ๊ธฐ์กด ๋ฐฉ์ (๊ธธ์ด๊ฐ ๋ค๋ฅด๋ฉด ์งง์ ์ชฝ์ ๋ง์ถฐ์ง)
print(list(zip(numbers, letters))) # ์ถ๋ ฅ: [(1, 'a'), (2, 'b'), (3, 'c')]
# ์๋ก์ด ๋ฐฉ์ (strict=True)
try:
print(list(zip(numbers, letters, strict=True)))
except ValueError as e:
print(f"์ค๋ฅ ๋ฐ์: {e}") # ์ถ๋ ฅ: ์ค๋ฅ ๋ฐ์: zip() argument 2 is longer than argument 1
์ด์ ๋ฐ์ดํฐ๋ฅผ zipํ ๋ ์ค์๋ก ๊ธธ์ด๊ฐ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ด์. ๋ง์น ์งํผ๋ฅผ ์ ๊ธ ๋ ํ ์ชฝ์ด ๋ ๊ธธ๋ฉด ์๋ ค์ฃผ๋ ๊ฒ๊ณผ ๊ฐ์ฃ ! ๐ค
8. ๋ ๋์ ํ์ ์ถ๋ก
ํ์ด์ฌ 3.10์์๋ ํ์ ์ถ๋ก ๊ธฐ๋ฅ์ด ๋์ฑ ๊ฐ์ ๋์ด์. ํนํ ์ ๋ค๋ฆญ ํ์ ๊ณผ ๊ด๋ จ๋ ์ถ๋ก ์ด ๊ฐํ๋์ฃ .
from typing import TypeVar, Generic
T = TypeVar('T')
class Container(Generic[T]):
def __init__(self, item: T):
self.item = item
def process(container: Container[T]) -> T:
return container.item
result = process(Container("Hello"))
print(result) # ์ถ๋ ฅ: Hello
print(type(result)) # ์ถ๋ ฅ: <class>
</class>
์ด์ ํ์ ์ฒด์ปค๊ฐ ๋ ์ ํํ๊ฒ ํ์ ์ ์ถ๋ก ํ ์ ์์ด์. ๋ง์น ์ ๋ก ํ์ฆ๊ฐ ๋ ๋๋ํด์ง ๊ฒ ๊ฐ์ฃ ? ๐ต๏ธโโ๏ธ๐
๐ก Tip: ์ฌ๋ฅ๋ท์์ ํ์ด์ฌ 3.10์ ์๋ก์ด ๊ธฐ๋ฅ๋ค์ ํ์ฉํ ์ฝ๋ ์์ ๋ฅผ ๊ณต์ ํด๋ณด์ธ์. ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค์๊ฒ ํฐ ๋์์ด ๋ ๊ฑฐ์์!
ํ์ด์ฌ 3.10์ ์๋ก์ด ๊ธฐ๋ฅ๋ค, ์ ๋ง ๋๋จํ์ฃ ? ์ด์ ์ฐ๋ฆฌ์ ์ฝ๋๊ฐ ๋ ๊น๋ํ๊ณ , ์์ ํ๊ณ , ํจ์จ์ ์ผ๋ก ๋ณํ ์ ์์ ๊ฒ ๊ฐ์์. ํ์ง๋ง ์ฌ๊ธฐ์ ๋์ด ์๋์์! ํ์ด์ฌ 3.11๋ ์ฐ๋ฆฌ๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ต๋๋ค. ๋ค์ ์น์ ์์ ๊ณ์ํด์ ์์๋ณผ๊น์? ๐
๐ Python 3.11์ ์๋ก์ด ๊ธฐ๋ฅ๋ค
2022๋ 10์์ ์ถ์๋ ํ์ด์ฌ 3.11์ ์ ๋ง ๋ง์ ๊ธฐ๋๋ฅผ ๋ฐ์์ด์. ํนํ ์ฑ๋ฅ ๊ฐ์ ์ ํฐ ์ด์ ์ ๋ง์ท๋ค๊ณ ํ๋๋ฐ, ๊ณผ์ฐ ์ด๋ค ๋ณํ๊ฐ ์์์๊น์? ๋ง์น ์ํผ์นด์ ์ ๋ชจ๋ธ์ ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ์ฒ๋ผ ์ค๋ ๋ ๋ง์์ผ๋ก ์ดํด๋ณผ๊น์? ๐๏ธ๐จ
1. ์ฑ๋ฅ ๊ฐ์
ํ์ด์ฌ 3.11์ ๊ฐ์ฅ ํฐ ํน์ง์ ๋ฐ๋ก ์ฑ๋ฅ ๊ฐ์ ์ด์์. ํ๊ท ์ ์ผ๋ก 10-60% ์ ๋ ๋นจ๋ผ์ก๋ค๊ณ ํ๋๋ฐ, ์ด๋ ์ ๋ง ๋๋จํ ๋ฐ์ ์ด์ฃ !
import time
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
start = time.perf_counter()
result = fibonacci(30)
end = time.perf_counter()
print(f"๊ฒฐ๊ณผ: {result}")
print(f"์คํ ์๊ฐ: {end - start:.4f}์ด")
์ด ์ฝ๋๋ฅผ ํ์ด์ฌ 3.10๊ณผ 3.11์์ ๊ฐ๊ฐ ์คํํด๋ณด๋ฉด, 3.11์์ ํจ์ฌ ๋น ๋ฅด๊ฒ ๋์ํ๋ ๊ฑธ ํ์ธํ ์ ์์ด์. ๋ง์น ๊ฑฐ๋ถ์ด๊ฐ ํ ๋ผ๋ก ๋ณ์ ํ ๊ฒ ๊ฐ์ฃ ? ๐ขโก๏ธ๐ฐ
๐ ์๋ ์ ! ํ์ด์ฌ 3.11์ ์ฑ๋ฅ ๊ฐ์ ์ผ๋ก ์ฌ๋ฌ๋ถ์ ํ๋ก๊ทธ๋จ์ด ๋ ๋น ๋ฅด๊ฒ ๋์ํ ๊ฑฐ์์. ์ฌ๋ฅ๋ท์์ ๊ณต์ ํ๋ ํ๋ก์ ํธ๋ค๋ ๋์ฑ ๋น ๋ฅด๊ณ ํจ์จ์ ์ผ๋ก ์คํ๋ ์ ์๊ฒ ์ฃ ?
2. ๋ ๋์ ์ค๋ฅ ๋ฉ์์ง
ํ์ด์ฌ 3.11์์๋ ์ค๋ฅ ๋ฉ์์ง๊ฐ ๋์ฑ ์์ธํด์ง๊ณ ์ ์ฉํด์ก์ด์. ํนํ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ํํ ์์น๋ฅผ ์๋ ค์ฃผ๋ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋์ฃ .
def divide(a, b):
return a / b
try:
result = divide(10, 0)
except ZeroDivisionError as e:
print(f"์ค๋ฅ ๋ฐ์: {e}")
print(f"์ค๋ฅ ์์น: {e.__traceback__.tb_lineno}๋ฒ ์ค")
์ด์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋ ์ ํํ ์ด๋ ์ค์์ ๋ฌธ์ ๊ฐ ์๊ฒผ๋์ง ๋ฐ๋ก ์ ์ ์์ด์. ๋ง์น GPS๊ฐ ์ ํํ ์์น๋ฅผ ์๋ ค์ฃผ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ ! ๐บ๏ธ๐
3. ์์ธ ๊ทธ๋ฃน (Exception Groups)
ํ์ด์ฌ 3.11์์๋ ์ฌ๋ฌ ๊ฐ์ ์์ธ๋ฅผ ๋์์ ์ฒ๋ฆฌํ ์ ์๋ ์์ธ ๊ทธ๋ฃน ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋์ด์.
def risky_operation(x):
if x < 0:
raise ValueError("์์๋ ํ์ฉ๋์ง ์์ต๋๋ค.")
if x > 100:
raise OverflowError("๋๋ฌด ํฐ ์ซ์์
๋๋ค.")
return 100 / x
try:
risky_operation(-5)
risky_operation(150)
risky_operation(0)
except* ValueError as e:
print(f"ValueError ๋ฐ์: {e}")
except* OverflowError as e:
print(f"OverflowError ๋ฐ์: {e}")
except* ZeroDivision Error as e:
print(f"ZeroDivisionError ๋ฐ์: {e}")
์ด๋ ๊ฒ ํ๋ฉด ์ฌ๋ฌ ์ข ๋ฅ์ ์์ธ๋ฅผ ํ ๋ฒ์ ์ฒ๋ฆฌํ ์ ์์ด์. ๋ง์น ์ฌ๋ฌ ๊ฐ์ง ๋ฌธ์ ๋ฅผ ๋์์ ํด๊ฒฐํ๋ ์ํผํ์ด๋ก ๊ฐ์ฃ ? ๐ฆธโโ๏ธ
4. ํ์ ํํธ ๊ฐ์
ํ์ด์ฌ 3.11์์๋ ํ์
ํํธ ๊ธฐ๋ฅ์ด ๋์ฑ ๊ฐํ๋์ด์. ํนํ typing.Self
ํ์
์ด ์ถ๊ฐ๋์ด ํด๋์ค ๋ฉ์๋์ ๋ฐํ ํ์
์ ๋ ์ ํํ๊ฒ ์ง์ ํ ์ ์๊ฒ ๋์ฃ .
from typing import Self
class ChainableList:
def __init__(self, values: list[int]):
self.values = values
def append(self, value: int) -> Self:
self.values.append(value)
return self
def extend(self, values: list[int]) -> Self:
self.values.extend(values)
return self
chain = ChainableList([1, 2, 3]).append(4).extend([5, 6])
print(chain.values) # ์ถ๋ ฅ: [1, 2, 3, 4, 5, 6]
์ด์ ๋ฉ์๋ ์ฒด์ด๋์ ์ฌ์ฉํ ๋ ํ์ ํํธ๋ฅผ ๋ ์ ํํ๊ฒ ์ ๊ณตํ ์ ์์ด์. ๋ง์น ๋๋ฏธ๋ ธ๋ฅผ ๋ ์ ํํ๊ฒ ์ธ์ธ ์ ์๊ฒ ๋ ๊ฒ ๊ฐ์ฃ ? ๐
5. TOML ์ง์
ํ์ด์ฌ 3.11๋ถํฐ๋ TOML(Tom's Obvious, Minimal Language) ํ์ผ ํ์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํด์. ์ด์ ๋ณต์กํ ์ค์ ํ์ผ์ ๋ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์๊ฒ ๋์ฃ .
import tomllib
# config.toml ํ์ผ ๋ด์ฉ:
# [database]
# host = "localhost"
# port = 5432
# user = "admin"
with open("config.toml", "rb") as f:
config = tomllib.load(f)
print(f"๋ฐ์ดํฐ๋ฒ ์ด์ค ํธ์คํธ: {config['database']['host']}")
print(f"๋ฐ์ดํฐ๋ฒ ์ด์ค ํฌํธ: {config['database']['port']}")
TOML ํ์ผ์ ์ฝ๊ธฐ ์ฝ๊ณ ์์ฑํ๊ธฐ ํธํด์, ํ๋ก์ ํธ์ ์ค์ ์ ๊ด๋ฆฌํ๊ธฐ๊ฐ ํจ์ฌ ์์ํด์ก์ด์. ๋ง์น ๋ณต์กํ ๋ ์ํผ๋ฅผ ๊ฐ๋จํ ์๋ฆฌ ์ฑ ์ผ๋ก ์ ๋ฆฌํ ๊ฒ ๊ฐ์ฃ ? ๐จโ๐ณ๐
6. ๋ ๋น ๋ฅธ ์์ ์๊ฐ
ํ์ด์ฌ 3.11์์๋ ์ธํฐํ๋ฆฌํฐ์ ์์ ์๊ฐ์ด ํฌ๊ฒ ๊ฐ์ ๋์ด์. ํนํ ๋ง์ ๋ชจ๋์ importํ๋ ๋๊ท๋ชจ ํ๋ก์ ํธ์์ ๊ทธ ํจ๊ณผ๊ฐ ๋๋๋ฌ์ง์ฃ .
import time
import sys
start = time.perf_counter()
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
end = time.perf_counter()
print(f"๋ชจ๋ import ์๊ฐ: {end - start:.4f}์ด")
print(f"ํ์ด์ฌ ๋ฒ์ : {sys.version}")
์ด ์ฝ๋๋ฅผ ํ์ด์ฌ 3.10๊ณผ 3.11์์ ๊ฐ๊ฐ ์คํํด๋ณด๋ฉด, 3.11์์ ๋ชจ๋ import ์๊ฐ์ด ํจ์ฌ ์งง์์ง ๊ฑธ ํ์ธํ ์ ์์ด์. ๋ง์น ํฐ๋ณด ์์ง์ ๋จ ๊ฒ์ฒ๋ผ ๋นจ๋ผ์ก์ฃ ! ๐
7. ํฅ์๋ ๋น๋๊ธฐ ์์ ์ทจ์
ํ์ด์ฌ 3.11์์๋ ๋น๋๊ธฐ ์์
์ ๋ ์ธ๋ฐํ๊ฒ ์ ์ดํ ์ ์๊ฒ ๋์ด์. ํนํ asyncio.TaskGroup
์ด ์ถ๊ฐ๋์ด ์ฌ๋ฌ ์์
์ ๋์์ ์คํํ๊ณ ๊ด๋ฆฌํ๊ธฐ๊ฐ ๋ ์ฌ์์ก์ฃ .
import asyncio
async def fetch_data(url):
print(f"{url} ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๋ ์ค...")
await asyncio.sleep(1) # ๋คํธ์ํฌ ์์ฒญ์ ์๋ฎฌ๋ ์ด์
print(f"{url} ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์๋ฃ!")
return f"Data from {url}"
async def main():
async with asyncio.TaskGroup() as tg:
task1 = tg.create_task(fetch_data("https://api1.example.com"))
task2 = tg.create_task(fetch_data("https://api2.example.com"))
task3 = tg.create_task(fetch_data("https://api3.example.com"))
results = [task1.result(), task2.result(), task3.result()]
print(f"๋ชจ๋ ๋ฐ์ดํฐ: {results}")
asyncio.run(main())
์ด์ ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ ๋ ์ฝ๊ฒ ๊ด๋ฆฌํ๊ณ ์ ์ดํ ์ ์์ด์. ๋ง์น ์ฌ๋ฌ ๊ฐ์ ์ ์๋ฅผ ๋์์ ๋๋ฆฌ๋ ์์ปค์ค ๊ณต์ฐ์ฒ๋ผ ๋ฉ์ง์ฃ ? ๐ญ
8. ์๋ก์ด ์๊ฐ ์กด API
ํ์ด์ฌ 3.11์์๋ zoneinfo
๋ชจ๋์ด ๊ฐ์ ๋์ด ์๊ฐ๋ ์ฒ๋ฆฌ๊ฐ ๋์ฑ ํธ๋ฆฌํด์ก์ด์.
from zoneinfo import ZoneInfo
from datetime import datetime, timedelta
seoul_time = datetime.now(ZoneInfo("Asia/Seoul"))
ny_time = datetime.now(ZoneInfo("America/New_York"))
print(f"์์ธ ์๊ฐ: {seoul_time}")
print(f"๋ด์ ์๊ฐ: {ny_time}")
# ์๊ฐ๋ ๋ณํ
seoul_to_ny = seoul_time.astimezone(ZoneInfo("America/New_York"))
print(f"์์ธ ์๊ฐ์ ๋ด์ ์๊ฐ์ผ๋ก: {seoul_to_ny}")
์ด์ ์ ์ธ๊ณ ์๊ฐ์ ๋ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์์ด์. ๋ง์น ์ ์ธ๊ณ ์๊ณ๋ฅผ ํ๋์ ๋ณผ ์ ์๋ ์ปจํธ๋กค ํ์๋ฅผ ๊ฐ์ง ๊ฒ ๊ฐ์ฃ ? ๐โฐ
๐ก Tip: ์ฌ๋ฅ๋ท์์ ํ์ด์ฌ 3.11์ ์๋ก์ด ๊ธฐ๋ฅ๋ค์ ํ์ฉํ ํ๋ก์ ํธ๋ฅผ ๊ณต์ ํด๋ณด์ธ์. ํนํ ์ฑ๋ฅ ๊ฐ์ ํจ๊ณผ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ฒค์น๋งํฌ ๊ฒฐ๊ณผ๋ ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค์๊ฒ ํฐ ๋์์ด ๋ ๊ฑฐ์์!
ํ์ด์ฌ 3.11์ ์๋ก์ด ๊ธฐ๋ฅ๋ค, ์ ๋ง ๋๋จํ์ฃ ? ์ด์ ์ฐ๋ฆฌ์ ์ฝ๋๊ฐ ๋ ๋น ๋ฅด๊ณ , ์์ ํ๊ณ , ํจ์จ์ ์ผ๋ก ๋์ํ ์ ์๊ฒ ๋์ด์. ์ด๋ฌํ ๋ณํ๋ค์ ์ฐ๋ฆฌ๊ฐ ๋ ๋์ ์ํํธ์จ์ด๋ฅผ ๋ง๋ค ์ ์๊ฒ ํด์ฃผ์ฃ . ๐
ํ์ด์ฌ 3.9๋ถํฐ 3.11๊น์ง์ ๋ณํ๋ฅผ ์ดํด๋ณด๋ฉด, ํ์ด์ฌ์ด ์ผ๋ง๋ ๋น ๋ฅด๊ฒ ๋ฐ์ ํ๊ณ ์๋์ง ์ ์ ์์ด์. ์๋ก์ด ๊ธฐ๋ฅ๋ค์ ์ ํ์ฉํ๋ฉด, ์ฌ๋ฌ๋ถ์ ์ฝ๋ฉ ์ค๋ ฅ๋ ํจ๊ป ์ฑ์ฅํ ์ ์์ ๊ฑฐ์์. ์ฌ๋ฅ๋ท์์ ์ด๋ฐ ์๋ก์ด ๊ธฐ๋ฅ๋ค์ ํ์ฉํ ํ๋ก์ ํธ๋ฅผ ๊ณต์ ํ๋ฉด ์ด๋จ๊น์? ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค์๊ฒ ์๊ฐ์ ์ฃผ๊ณ , ํจ๊ป ์ฑ์ฅํ ์ ์๋ ์ข์ ๊ธฐํ๊ฐ ๋ ๊ฑฐ์์! ๐๐จโ๐ป๐ฉโ๐ป
์, ์ด์ ์ฌ๋ฌ๋ถ์ ํ์ด์ฌ์ ์ต์ ๋ฒ์ ๋ค์ ๋ํด ์ ์๊ฒ ๋์ด์. ์ด ์ง์์ ํ์ฉํด์ ๋ ๋ฉ์ง ํ๋ก๊ทธ๋จ์ ๋ง๋ค์ด๋ณด์ธ์. ํ์ด์ฌ์ ์ธ๊ณ๋ ๋์์ด ๋๊ณ ๊น๋ต๋๋ค. ๊ณ์ํด์ ํํํ๊ณ ๋ฐฐ์ฐ๋ ์ฆ๊ฑฐ์์ ๋๊ปด๋ณด์ธ์! ๐โจ
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ