๐Python ์ ํ ๋ฉ๋ชจโ๐-โ์ ์๊พธ ์จ์?
17744 ๋จ์ด computersciencedatasciencepythonwebdev
Python์ ๋์ ์ ํ ์ธ์ด๋ก ์๋ก ๋ค๋ฅธ ์ ํ์ ๋ณ์๋ฅผ ์๋นํ ์์ ๋กญ๊ฒ ์กฐ์ํ ์ ์์ต๋๋ค.๊ทธ๋ฌ๋ ์ฝ๋๋ฅผ ์์ฑํ ๋, ์ฐ๋ฆฌ๋ ์ด๋ค ๋ฐฉ์์ผ๋ก ์ด๋ค ์ ํ์ ๋ณ์๋ฅผ ์ฌ์ฉํ ๊ฒ์ธ์ง๋ฅผ ๊ฐ์ ํ๋ค. (์ด๊ฒ์ ์๊ณ ๋ฆฌ์ฆ์ด๋ ์ ๋ฌด ๋ ผ๋ฆฌ์ ์ ํ์ผ๋ก ์ธํ ๊ฒ์ผ ์๋ ์๋ค.)ํ๋ก๊ทธ๋จ์ด ์ ํํ๊ฒ ์๋ํ๊ธฐ ์ํด์๋ ์ ์ก ์ค๋ฅ ์ ํ์ ๋ฐ์ดํฐ์ ๊ด๋ จ๋ ์ค๋ฅ๋ฅผ ๋นจ๋ฆฌ ๋ฐ๊ฒฌํ๋ ๊ฒ์ด ์ฐ๋ฆฌ์๊ฒ ๋งค์ฐ ์ค์ํ๋ค.
์ ์งํ๋คโโPython(3.6+) ํ๋ ๋ฒ์ ์ ๋์ duck ํ์์ ๋ณ์ ํ์, ํด๋์ค ํ๋, ํ๋ผ๋ฏธํฐ์ ๋ฐํ ๊ฐ์ ๋ํ ์ฃผ์์ ์ง์ํฉ๋๋คโโํจ์ ์๋:
typing
ํจํค์ง๋ณธ๊ณ ์์ ๋๋ ์ ํ ์ฃผ์์ ์ฌ์ฉํ๋ ๊ธฐ์ด ์ง์๊ณผ ์์๋ฅผ ์ค๋ช ํ๊ณ ์ต์ข ์ ์ผ๋ก ๊ทธ๊ฒ์ด ์ ๋๋ฅผPython ๊ฐ๋ฐ์๋ก์์ ์ํ์ ๋์ฑ ์ฝ๊ฒ ํ๋์ง ์ค๋ช ํ๊ณ ์ถ๋ค๐.
์ฐ์ ์ ํ ์ฃผ์์ด ๋ฌด์์ธ์ง ์์๋ณด์
โถ ์ ํ ๋ฉ๋ชจโ-โ๊ธฐ์ด ์ง์
์ ํ ์์ฒด๋ ๋ณ์์ ๊ธฐ๋ณธ ์ ํ์ ๋ํ๋ด๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
str
int
float
bool
complex
bytes
๊ฐ์ฅ ๊ฐ๋จํ ์ํฉ์์ ์ฃผ์์ ์ง์ ์์ํ ์ ํ์ ํฌํจํ๋ค.๋ค์์ ๋์ฑ ๋ณต์กํ ์ํฉ์ ํ ๋ก ํ ๊ฒ์ด๋ค.๊ธฐ๋ณธ ํด๋์ค๋ฅผ ์ฃผ์์ผ๋ก ์ง์ ํ๋ฉด ํ์ ํญ๋ชฉ์ ์ธ์คํด์ค๋ฅผ ๊ฐ์ผ๋ก ์ ๋ฌํ ์ ์์ต๋๋ค.๋จ, ๊ธฐ๋ณธ ํด๋์ค์์๋ง ์คํํ ์ ์๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ณ์ ์ฃผ์์ ํ์ง๋ถ ๋ค์ ์ฌ์นญ์ผ๋ก ์ฐ์ธ๋ค.๊ทธ๋ฆฌ๊ณ ๊ฐ์ ์ด๊ธฐํํ ์ ์์ต๋๋ค.์:
price: int = 5
title: "str"
ํจ์ ๋งค๊ฐ ๋ณ์์ ์ฃผ์ ๋ฐฉ์์ ๋ณ์์ ๊ฐ๊ณ ๋ฐํ ๊ฐ์ ํ์ดํ->
์ดํ์ ์ฝ๋ก ๋ค์ ์ง์ ๋ฉ๋๋ค.python ํจ์์ ํ์ ์ฃผ์์ ์ฌ์ฉํ๋ ์์๋ฅผ ๋ค๊ฒ ์ต๋๋ค.def func(a: int, b: float) -> str:
a: str = f"{a}, {b}"
return a
ํด๋์ค ํ๋์ ๋ํด ํด๋์ค๋ฅผ ์ ์ํ ๋ ์ฃผ์์ ๋ช
์์ ์ผ๋ก ์ง์ ํด์ผ ํฉ๋๋ค.๊ทธ๋ฌ๋ ๋ถ์๊ธฐ๋ __init__
๋ฐฉ๋ฒ์ ๋ฐ๋ผ ์๋์ผ๋ก ์ถ์ ํ ์ ์์ง๋ง ์ด ๊ฒฝ์ฐ ์คํํ ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.class Book:
title: "str"
author: str
def __init__(self, title: "str, author: str) -> None:"
self.title = title
self.author = author
b: Book = Book(title="Fahrenheit 451", author="Bradbury")
โถ ์ ํ ๋ฉ๋ชจโ-โ๋ด์ฅ ์ ํ
ํ์ค ์ ํ์ ์ฃผ์์ผ๋ก ์ฌ์ฉํ ์ ์์ง๋ง ๋ชจ๋typing
์๋ ์ ์ฉํ ๊ฒ๋ค์ด ๋ง์ด ์จ๊ฒจ์ ธ ์๋ค.๊ทธ๊ฒ์ ํ์ ๋ชจ๋์ ๋ด
์๋ค.
์ผ.๏ธโฃ ์ ํ ๊ฐ๋ฅ
์ ํint
์ผ๋ก ๋ณ์๋ฅผ ํ์ํ๊ณ None ๊ฐ์ ์ง์ ํ๋ ค๊ณ ํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
Incompatible types in assignment (expression has type "None", variable has type "int")
์ด ๊ฒฝ์ฐ ์
๋ ฅ ๋ชจ๋์ ํน์ ์ ํ์ ํ์ํ๋ ๋ฐ ์ฌ์ฉํ ์ค๋ช
Optional
์ ์ ๊ณตํฉ๋๋ค.์ ํ์ ๋ณ์์ ์ ํ์ ๋๊ดํธ๋ก ํ์๋ฉ๋๋ค.
from typing import Optional
amount: int
amount: None # Gives "Incompatible types" error
price: Optional[int]
price: None # Will work!
์ด.๏ธโฃ ์ด๋ค
๋๋๋ก ๋ณ์์ ๊ฐ๋ฅํ ์ ํ์ ์ ํํ๊ณ ์ถ์ง ์์ต๋๋ค.์๋ฅผ ๋ค์ด, ๋ง์ฝ ์ด๊ฒ์ด ์ ๋ง ์ค์ํ์ง ์๋ค๋ฉด, ํน์ ๋ค๋ฅธ ์ ํ์ ์ฒ๋ฆฌ๋ฅผ ๊ณํํ๊ณ ์๋ค๋ฉด.์ด ๊ฒฝ์ฐ ์ฃผ์Any
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.๋ค์ ์ฝ๋์ ๋ํด ๋งน์ธํ์ง ์์ต๋๋ค.
some_item: Any = 1
print(some_item)
print(some_item.startswith("hello"))
print(some_item // 0)
๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ ์ฌ์ฉํ์ง ์์ต๋๊นobject
?๊ทธ๋ฌ๋ ์ด ๊ฒฝ์ฐ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ ์ ์์ง๋ง ์ธ์คํด์ค๋ก๋ง ๊ฐ์ฃผํ ์ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋คobject
.
some_object: object
print(some_object)
print(some_object.startswith("hello)) # ERROR: "object" has no attribute "startswith"
print(some_object // 0) # ERROR: Unsupported operand types for // ("object" and "int")
์ผ.๏ธโฃ ํํ
๋ชจ๋ ์ ํ์ด ์๋ ์ผ๋ถ ์ ํ๋ง ์ฌ์ฉํ ์ ์๋๋ก ํ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ ์ฃผ์typing.Union
์ ์ฌ์ฉํ์ฌ ๊ดํธ์ ์ ํ ๋ชฉ๋ก์ ํ์ํ ์ ์์ต๋๋ค.
def hundreds(x: Union[int, float]) -> int:
return (int(x) // 100) % 100
hundreds(100.0)
hundreds(100)
hundreds("100")
# ERROR: Argument 1 to "hundreds" has incompatible type "str"; expected "Union[int, float]"
์ฐธ๊ณ ๋ก ์ฃผ์Optional[T]
์ Union[T, None]
๊ณผ ๊ฐ๋ค. ๋น๋ก ์ด๋ฐ ๊ธฐํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ์ง๋ ์์ง๋ง.
์ฌ.๏ธโฃ ์์ฅํ๋ค
์ ํ ์ฃผ์ ๋ฉ์ปค๋์ฆ์ ๋ฒ์ฉ ๋ฉ์ปค๋์ฆPEP484โ-โGenerics์ ์ง์ํ๋ฉฐ, ์์ธํ ์ ๋ณด๋ ๋ณธ๊ณ ์ ๋ ๋ฒ์งธ ๋ถ๋ถ์ ์ฐธ์กฐํ์ญ์์ค. ์ด ๋ฉ์ปค๋์ฆ์ ์ฉ๊ธฐ์ ๋ฒ์ฉ์ ์ ์ฅ๋ ์์ ์ ํ์ ์ง์ ํ ์ ์์ต๋๋ค.
์ค.๏ธโฃ ๋ชฉ๋ก
๋ณ์์ ๋ชฉ๋ก์ด ์์์ ํ์ํ๋ ค๋ฉด ๋ชฉ๋ก ์ ํ์ ์ฃผ์์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.๊ทธ๋ฌ๋ ๋ชฉ๋ก์ ์ด๋ค ์์๊ฐ ํฌํจ๋์ด ์๋์ง ์ง์ ํ๋ ค๋ฉด ์ด๋ฌํ ์ฃผ์์ ๋ ์ด์ ์ ํจํ์ง ์์ต๋๋ค.์ด๋ฅผ ์ํดtyping.List
๊ฐ ์๋ค.์ ํํ ์ ์๋ ๋ณ์ ํ์์ ์ง์ ํ๋ ๋ฐฉ์๊ณผ ์ ์ฌํฉ๋๋ค. ๊ดํธ์ ๋ชฉ๋ก ํญ๋ชฉ์ ํ์์ ์ง์ ํฉ๋๋ค.
titles: List[str] = ["hello", "world"]
titles.append(100500)
# ERROR: Argument 1 to "hundreds" has incompatible type "str"; expected "Union[int, float]"
titles = ["hello", 1]
# ERROR: List item 1 has incompatible type "int"; expected "str"
items: List = ["hello", 1]
# Everything is good!
์ด ๋ชฉ๋ก์ ๋ถํ์คํ ์๋์ ์ ์ฌํ ํญ๋ชฉ์ด ํฌํจ๋์ด ์๋ค๊ณ ๊ฐ์ ํ์ญ์์ค.๊ทธ๋ฌ๋ ์ฃผ์ ์์์๋ ์ ํ์ด ์์ต๋๋ค. Any
, Optional
, List
๋ฐ ๊ธฐํ ์์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.์์ ์ ํ์ด ์ง์ ๋์ง ์์ผ๋ฉด Any
๋ก ๊ฐ์ ํฉ๋๋ค.
๋ชฉ๋ก ์ธ์ ์ ์ฌํ ์งํฉ ์ฃผ์๋ ์์ต๋๋ค: typing.Set
๊ณผtyping.FrozenSet
.
์ก.๏ธโฃ ๋ค์ค ๊ทธ๋ฃน
๋ชฉ๋ก๊ณผ ๋ฌ๋ฆฌ ๋ฉํ๊ทธ๋ฃน์ ์ผ๋ฐ์ ์ผ๋ก ๋ค๋ฅธ ์ ํ์ ์์์ ์ฌ์ฉ๋ฉ๋๋ค.๋ฌธ๋ฒ์ ๋น์ทํ์ง๋ง ํ ๊ฐ์ง ๋ค๋ฅด๋ค. ์์กฐ์ ๊ฐ ์์์ ์ ํ์ ๊ฐ๊ฐ ๋ค๋ชจ๋ ๊ดํธ๋ก ํ์๋๋ค.
๋ชฉ๋ก๊ณผ ์ ์ฌํ ๋ฉํ๊ทธ๋ฃน์ ์ฌ์ฉํ ๊ณํ์ธ ๊ฒฝ์ฐ ์ ์ ์๋ ์์ ๋์ผํ ์ ํ์ ์์๋ฅผ ์ ์ฅํ๋ ค๋ฉด ์๋ต ๋ฒํธ ...
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ํฐํฐ ์ ํ์ ์ง์ ํ์ง ์๋ ๋ฉ๋ชจTuple
๋ Tuple[Any,ย ...]
์ ๋์ผํ๊ฒ ์๋ํฉ๋๋ค.
price_container: Tuple[int] = (1,)
price_container: ("hello")
# ERROR: Incompatible types in assignment (expression has type "str", variable has type "Tuple[int]")
price_container = (1, 2)
# ERROR: Incompatible types in assignment (expression has type "Tuple[int, int]", variable has type "Tuple[int]")
price_with_title: Tuple[int, str] = (1, "hello")
# Everything is good!
prices: Tuple[int, ...] = (1, 2)
prices: (1,)
prices: (1, "str")
# ERROR: Incompatible types in assignment (expression has type "Tuple[int, str]", variable has type "Tuple[int]")
something: Tuple = (1, 2, "hello")
# Everything is good!
์น .๏ธโฃ ์ฌ์
์ฌ์ typing.Dict
์ ์ฌ์ฉ๋ฉ๋๋ค.ํค ์ ํ๊ณผ ๊ฐ ์ ํ์ ๋ํ ์ค๋ช
์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
book_authors: Dict[str, str] = {"Fahrenheit 451": "Bradbury"}
book_authors["1984"] = 0
# ERROR: Incompatible types in assignment (expression has type "int", target has type "str")
book_authors[1984] = "Orwell"
# ERROR: Invalid index type "int" for "Dict[str, str]"; expected type "str"
์ ์ฌ ์ฌ์ฉtyping.DefaultDict
๋ฐ typing.OrderedDict
ํ.๏ธโฃ ํจ์ ์คํ ๊ฒฐ๊ณผ
๋ชจ๋ ์ข
๋ฅ์ ์ฃผ์์ ํจ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ํ๋ ํ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.ํ์ง๋ง ํน๋ณํ ๊ฒฝ์ฐ๋ ์๋ค.
ํจ์๊ฐ ๊ฒฐ๊ณผ (์: how print
๋ฅผ ๋ฐํํ์ง ์์ผ๋ฉด ๊ฒฐ๊ณผ๋ ํญ์ ๊ฐ์ต๋๋ค None
.์ฐ๋ฆฌ๋ ๋ํ ์ฃผ์None
์ ์ฌ์ฉํ๋ค.
์ด๋ฌํ ํจ์๋ฅผ ์์ฑํ๋ ์ฌ๋ฐ๋ฅธ ์ต์
์ ๋ช
์์ ๋ฐํNone
, ์ง์ ๋์ง ์์ ๊ฐ์ ๋ฐํ ๋ฐ ํธ์ถ๋์ง ์์ ์ข
๋ฃreturn
์
๋๋ค.
def nothing(a: int) -> None:
if a == 1:
return
elif a == 2:
return
elif a == 3:
return "" # No return value expected
else:
pass
ํจ์๊ฐ ์ ์ด๋ฅผ ๋ฐํํ์ง ์๋ ๊ฒฝ์ฐ (์: how sys.exit
๋ฉ๋ชจ NoReturn
๋ฅผ ์ฌ์ฉํฉ๋๋ค.
def forever() -> NoReturn:
while True:
pass
๋ง์ฝ ์ด๊ฒ์ด ์์ฑ ํจ์, ์ฆ ๊ทธ ์ฃผ์ฒด์ ์ฐ์ฐ์ yield๊ฐ ํฌํจ๋์ด ์๋ค๋ฉด, ๋๋์์ค๋ ํจ์Iterable[T]
์ ๋ํด ์ฃผ์Generator[YT, ST, RT]
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
def generate_two() -> Iterable[int]:
yield 1
yield "2"
# ERROR: Incompatible types in "yield" (actual type "str", expected type "int")
๊ฒฐ๋ก ์ด ์๋๋ผ
๋ง์ ๊ฒฝ์ฐ์ ์ ํ ๋ชจ๋์ ์ ๋นํ ์ ํ์ ๊ฐ์ง๊ณ ์์ง๋ง, ๋๋ ๋ชจ๋ ๋ด์ฉ์ ํฌํจํ์ง ์๋๋ค. ์๋ํ๋ฉด ๊ทธ ํ์๋ ๋ฌ์ฌํ ๊ฒ๊ณผ ์ ์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค.์๋ฅผ ๋ค์ด, Iterator
์ collections.abc.Iterator
, typing.SupportsInt
์ ๊ณตํต ๋ฒ์ ์ผ๋ก, ๋์ ์ง์ ๋ฐฉ๋ฒ__int__
๋๋ Callable
์ง์ ๋ฐฉ๋ฒ__call__
์ ํจ์์ ๋์์ ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค
์ด ํ์ค์ ์ ์ ๋ถ์๊ธฐ์ ์ ๋ณด๋ง ํฌํจํ๋ ์ฃผ์๊ณผ ๋ฉ๋ชจ๋ฆฌ ํ์ผ ํ์์ผ๋ก ์ฃผ์์ ํ์์ ์ ์ํ๋ค.
์์ธํ ๋ณด๊ธฐ
์ด ๋ฌธ์๊ฐ ๋์์ด ๋๋ค๋ฉด๐ ๋๋๐ ์๋ ๋ฒํผ์ ๋๋ฅด๊ฑฐ๋ ํ์ด์ค๋ถ์ ์ด ๊ธ์ ๊ณต์ ํ๋ฉด ์น๊ตฌ๋ ์ด์ต์ ๋ณผ ์ ์๋ค.
https://subscribe.to/raevskymichail
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐Python ์ ํ ๋ฉ๋ชจโ๐-โ์ ์๊พธ ์จ์?), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/mikhailraevskiy/python-s-type-annotations-why-you-always-should-use-it-4lh2
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
์ ํ
int
์ผ๋ก ๋ณ์๋ฅผ ํ์ํ๊ณ None ๊ฐ์ ์ง์ ํ๋ ค๊ณ ํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.Incompatible types in assignment (expression has type "None", variable has type "int")
์ด ๊ฒฝ์ฐ ์ ๋ ฅ ๋ชจ๋์ ํน์ ์ ํ์ ํ์ํ๋ ๋ฐ ์ฌ์ฉํ ์ค๋ช
Optional
์ ์ ๊ณตํฉ๋๋ค.์ ํ์ ๋ณ์์ ์ ํ์ ๋๊ดํธ๋ก ํ์๋ฉ๋๋ค.from typing import Optional
amount: int
amount: None # Gives "Incompatible types" error
price: Optional[int]
price: None # Will work!
์ด.๏ธโฃ ์ด๋ค
๋๋๋ก ๋ณ์์ ๊ฐ๋ฅํ ์ ํ์ ์ ํํ๊ณ ์ถ์ง ์์ต๋๋ค.์๋ฅผ ๋ค์ด, ๋ง์ฝ ์ด๊ฒ์ด ์ ๋ง ์ค์ํ์ง ์๋ค๋ฉด, ํน์ ๋ค๋ฅธ ์ ํ์ ์ฒ๋ฆฌ๋ฅผ ๊ณํํ๊ณ ์๋ค๋ฉด.์ด ๊ฒฝ์ฐ ์ฃผ์Any
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.๋ค์ ์ฝ๋์ ๋ํด ๋งน์ธํ์ง ์์ต๋๋ค.
some_item: Any = 1
print(some_item)
print(some_item.startswith("hello"))
print(some_item // 0)
๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ ์ฌ์ฉํ์ง ์์ต๋๊นobject
?๊ทธ๋ฌ๋ ์ด ๊ฒฝ์ฐ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ ์ ์์ง๋ง ์ธ์คํด์ค๋ก๋ง ๊ฐ์ฃผํ ์ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋คobject
.
some_object: object
print(some_object)
print(some_object.startswith("hello)) # ERROR: "object" has no attribute "startswith"
print(some_object // 0) # ERROR: Unsupported operand types for // ("object" and "int")
์ผ.๏ธโฃ ํํ
๋ชจ๋ ์ ํ์ด ์๋ ์ผ๋ถ ์ ํ๋ง ์ฌ์ฉํ ์ ์๋๋ก ํ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ ์ฃผ์typing.Union
์ ์ฌ์ฉํ์ฌ ๊ดํธ์ ์ ํ ๋ชฉ๋ก์ ํ์ํ ์ ์์ต๋๋ค.
def hundreds(x: Union[int, float]) -> int:
return (int(x) // 100) % 100
hundreds(100.0)
hundreds(100)
hundreds("100")
# ERROR: Argument 1 to "hundreds" has incompatible type "str"; expected "Union[int, float]"
์ฐธ๊ณ ๋ก ์ฃผ์Optional[T]
์ Union[T, None]
๊ณผ ๊ฐ๋ค. ๋น๋ก ์ด๋ฐ ๊ธฐํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ์ง๋ ์์ง๋ง.
์ฌ.๏ธโฃ ์์ฅํ๋ค
์ ํ ์ฃผ์ ๋ฉ์ปค๋์ฆ์ ๋ฒ์ฉ ๋ฉ์ปค๋์ฆPEP484โ-โGenerics์ ์ง์ํ๋ฉฐ, ์์ธํ ์ ๋ณด๋ ๋ณธ๊ณ ์ ๋ ๋ฒ์งธ ๋ถ๋ถ์ ์ฐธ์กฐํ์ญ์์ค. ์ด ๋ฉ์ปค๋์ฆ์ ์ฉ๊ธฐ์ ๋ฒ์ฉ์ ์ ์ฅ๋ ์์ ์ ํ์ ์ง์ ํ ์ ์์ต๋๋ค.
์ค.๏ธโฃ ๋ชฉ๋ก
๋ณ์์ ๋ชฉ๋ก์ด ์์์ ํ์ํ๋ ค๋ฉด ๋ชฉ๋ก ์ ํ์ ์ฃผ์์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.๊ทธ๋ฌ๋ ๋ชฉ๋ก์ ์ด๋ค ์์๊ฐ ํฌํจ๋์ด ์๋์ง ์ง์ ํ๋ ค๋ฉด ์ด๋ฌํ ์ฃผ์์ ๋ ์ด์ ์ ํจํ์ง ์์ต๋๋ค.์ด๋ฅผ ์ํดtyping.List
๊ฐ ์๋ค.์ ํํ ์ ์๋ ๋ณ์ ํ์์ ์ง์ ํ๋ ๋ฐฉ์๊ณผ ์ ์ฌํฉ๋๋ค. ๊ดํธ์ ๋ชฉ๋ก ํญ๋ชฉ์ ํ์์ ์ง์ ํฉ๋๋ค.
titles: List[str] = ["hello", "world"]
titles.append(100500)
# ERROR: Argument 1 to "hundreds" has incompatible type "str"; expected "Union[int, float]"
titles = ["hello", 1]
# ERROR: List item 1 has incompatible type "int"; expected "str"
items: List = ["hello", 1]
# Everything is good!
์ด ๋ชฉ๋ก์ ๋ถํ์คํ ์๋์ ์ ์ฌํ ํญ๋ชฉ์ด ํฌํจ๋์ด ์๋ค๊ณ ๊ฐ์ ํ์ญ์์ค.๊ทธ๋ฌ๋ ์ฃผ์ ์์์๋ ์ ํ์ด ์์ต๋๋ค. Any
, Optional
, List
๋ฐ ๊ธฐํ ์์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.์์ ์ ํ์ด ์ง์ ๋์ง ์์ผ๋ฉด Any
๋ก ๊ฐ์ ํฉ๋๋ค.
๋ชฉ๋ก ์ธ์ ์ ์ฌํ ์งํฉ ์ฃผ์๋ ์์ต๋๋ค: typing.Set
๊ณผtyping.FrozenSet
.
์ก.๏ธโฃ ๋ค์ค ๊ทธ๋ฃน
๋ชฉ๋ก๊ณผ ๋ฌ๋ฆฌ ๋ฉํ๊ทธ๋ฃน์ ์ผ๋ฐ์ ์ผ๋ก ๋ค๋ฅธ ์ ํ์ ์์์ ์ฌ์ฉ๋ฉ๋๋ค.๋ฌธ๋ฒ์ ๋น์ทํ์ง๋ง ํ ๊ฐ์ง ๋ค๋ฅด๋ค. ์์กฐ์ ๊ฐ ์์์ ์ ํ์ ๊ฐ๊ฐ ๋ค๋ชจ๋ ๊ดํธ๋ก ํ์๋๋ค.
๋ชฉ๋ก๊ณผ ์ ์ฌํ ๋ฉํ๊ทธ๋ฃน์ ์ฌ์ฉํ ๊ณํ์ธ ๊ฒฝ์ฐ ์ ์ ์๋ ์์ ๋์ผํ ์ ํ์ ์์๋ฅผ ์ ์ฅํ๋ ค๋ฉด ์๋ต ๋ฒํธ ...
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ํฐํฐ ์ ํ์ ์ง์ ํ์ง ์๋ ๋ฉ๋ชจTuple
๋ Tuple[Any,ย ...]
์ ๋์ผํ๊ฒ ์๋ํฉ๋๋ค.
price_container: Tuple[int] = (1,)
price_container: ("hello")
# ERROR: Incompatible types in assignment (expression has type "str", variable has type "Tuple[int]")
price_container = (1, 2)
# ERROR: Incompatible types in assignment (expression has type "Tuple[int, int]", variable has type "Tuple[int]")
price_with_title: Tuple[int, str] = (1, "hello")
# Everything is good!
prices: Tuple[int, ...] = (1, 2)
prices: (1,)
prices: (1, "str")
# ERROR: Incompatible types in assignment (expression has type "Tuple[int, str]", variable has type "Tuple[int]")
something: Tuple = (1, 2, "hello")
# Everything is good!
์น .๏ธโฃ ์ฌ์
์ฌ์ typing.Dict
์ ์ฌ์ฉ๋ฉ๋๋ค.ํค ์ ํ๊ณผ ๊ฐ ์ ํ์ ๋ํ ์ค๋ช
์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
book_authors: Dict[str, str] = {"Fahrenheit 451": "Bradbury"}
book_authors["1984"] = 0
# ERROR: Incompatible types in assignment (expression has type "int", target has type "str")
book_authors[1984] = "Orwell"
# ERROR: Invalid index type "int" for "Dict[str, str]"; expected type "str"
์ ์ฌ ์ฌ์ฉtyping.DefaultDict
๋ฐ typing.OrderedDict
ํ.๏ธโฃ ํจ์ ์คํ ๊ฒฐ๊ณผ
๋ชจ๋ ์ข
๋ฅ์ ์ฃผ์์ ํจ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ํ๋ ํ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.ํ์ง๋ง ํน๋ณํ ๊ฒฝ์ฐ๋ ์๋ค.
ํจ์๊ฐ ๊ฒฐ๊ณผ (์: how print
๋ฅผ ๋ฐํํ์ง ์์ผ๋ฉด ๊ฒฐ๊ณผ๋ ํญ์ ๊ฐ์ต๋๋ค None
.์ฐ๋ฆฌ๋ ๋ํ ์ฃผ์None
์ ์ฌ์ฉํ๋ค.
์ด๋ฌํ ํจ์๋ฅผ ์์ฑํ๋ ์ฌ๋ฐ๋ฅธ ์ต์
์ ๋ช
์์ ๋ฐํNone
, ์ง์ ๋์ง ์์ ๊ฐ์ ๋ฐํ ๋ฐ ํธ์ถ๋์ง ์์ ์ข
๋ฃreturn
์
๋๋ค.
def nothing(a: int) -> None:
if a == 1:
return
elif a == 2:
return
elif a == 3:
return "" # No return value expected
else:
pass
ํจ์๊ฐ ์ ์ด๋ฅผ ๋ฐํํ์ง ์๋ ๊ฒฝ์ฐ (์: how sys.exit
๋ฉ๋ชจ NoReturn
๋ฅผ ์ฌ์ฉํฉ๋๋ค.
def forever() -> NoReturn:
while True:
pass
๋ง์ฝ ์ด๊ฒ์ด ์์ฑ ํจ์, ์ฆ ๊ทธ ์ฃผ์ฒด์ ์ฐ์ฐ์ yield๊ฐ ํฌํจ๋์ด ์๋ค๋ฉด, ๋๋์์ค๋ ํจ์Iterable[T]
์ ๋ํด ์ฃผ์Generator[YT, ST, RT]
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
def generate_two() -> Iterable[int]:
yield 1
yield "2"
# ERROR: Incompatible types in "yield" (actual type "str", expected type "int")
๊ฒฐ๋ก ์ด ์๋๋ผ
๋ง์ ๊ฒฝ์ฐ์ ์ ํ ๋ชจ๋์ ์ ๋นํ ์ ํ์ ๊ฐ์ง๊ณ ์์ง๋ง, ๋๋ ๋ชจ๋ ๋ด์ฉ์ ํฌํจํ์ง ์๋๋ค. ์๋ํ๋ฉด ๊ทธ ํ์๋ ๋ฌ์ฌํ ๊ฒ๊ณผ ์ ์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค.์๋ฅผ ๋ค์ด, Iterator
์ collections.abc.Iterator
, typing.SupportsInt
์ ๊ณตํต ๋ฒ์ ์ผ๋ก, ๋์ ์ง์ ๋ฐฉ๋ฒ__int__
๋๋ Callable
์ง์ ๋ฐฉ๋ฒ__call__
์ ํจ์์ ๋์์ ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค
์ด ํ์ค์ ์ ์ ๋ถ์๊ธฐ์ ์ ๋ณด๋ง ํฌํจํ๋ ์ฃผ์๊ณผ ๋ฉ๋ชจ๋ฆฌ ํ์ผ ํ์์ผ๋ก ์ฃผ์์ ํ์์ ์ ์ํ๋ค.
์์ธํ ๋ณด๊ธฐ
์ด ๋ฌธ์๊ฐ ๋์์ด ๋๋ค๋ฉด๐ ๋๋๐ ์๋ ๋ฒํผ์ ๋๋ฅด๊ฑฐ๋ ํ์ด์ค๋ถ์ ์ด ๊ธ์ ๊ณต์ ํ๋ฉด ์น๊ตฌ๋ ์ด์ต์ ๋ณผ ์ ์๋ค.
https://subscribe.to/raevskymichail
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐Python ์ ํ ๋ฉ๋ชจโ๐-โ์ ์๊พธ ์จ์?), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/mikhailraevskiy/python-s-type-annotations-why-you-always-should-use-it-4lh2
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
some_item: Any = 1
print(some_item)
print(some_item.startswith("hello"))
print(some_item // 0)
some_object: object
print(some_object)
print(some_object.startswith("hello)) # ERROR: "object" has no attribute "startswith"
print(some_object // 0) # ERROR: Unsupported operand types for // ("object" and "int")
๋ชจ๋ ์ ํ์ด ์๋ ์ผ๋ถ ์ ํ๋ง ์ฌ์ฉํ ์ ์๋๋ก ํ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ ์ฃผ์
typing.Union
์ ์ฌ์ฉํ์ฌ ๊ดํธ์ ์ ํ ๋ชฉ๋ก์ ํ์ํ ์ ์์ต๋๋ค.def hundreds(x: Union[int, float]) -> int:
return (int(x) // 100) % 100
hundreds(100.0)
hundreds(100)
hundreds("100")
# ERROR: Argument 1 to "hundreds" has incompatible type "str"; expected "Union[int, float]"
์ฐธ๊ณ ๋ก ์ฃผ์Optional[T]
์ Union[T, None]
๊ณผ ๊ฐ๋ค. ๋น๋ก ์ด๋ฐ ๊ธฐํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ์ง๋ ์์ง๋ง.์ฌ.๏ธโฃ ์์ฅํ๋ค
์ ํ ์ฃผ์ ๋ฉ์ปค๋์ฆ์ ๋ฒ์ฉ ๋ฉ์ปค๋์ฆPEP484โ-โGenerics์ ์ง์ํ๋ฉฐ, ์์ธํ ์ ๋ณด๋ ๋ณธ๊ณ ์ ๋ ๋ฒ์งธ ๋ถ๋ถ์ ์ฐธ์กฐํ์ญ์์ค. ์ด ๋ฉ์ปค๋์ฆ์ ์ฉ๊ธฐ์ ๋ฒ์ฉ์ ์ ์ฅ๋ ์์ ์ ํ์ ์ง์ ํ ์ ์์ต๋๋ค.
์ค.๏ธโฃ ๋ชฉ๋ก
๋ณ์์ ๋ชฉ๋ก์ด ์์์ ํ์ํ๋ ค๋ฉด ๋ชฉ๋ก ์ ํ์ ์ฃผ์์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.๊ทธ๋ฌ๋ ๋ชฉ๋ก์ ์ด๋ค ์์๊ฐ ํฌํจ๋์ด ์๋์ง ์ง์ ํ๋ ค๋ฉด ์ด๋ฌํ ์ฃผ์์ ๋ ์ด์ ์ ํจํ์ง ์์ต๋๋ค.์ด๋ฅผ ์ํดtyping.List
๊ฐ ์๋ค.์ ํํ ์ ์๋ ๋ณ์ ํ์์ ์ง์ ํ๋ ๋ฐฉ์๊ณผ ์ ์ฌํฉ๋๋ค. ๊ดํธ์ ๋ชฉ๋ก ํญ๋ชฉ์ ํ์์ ์ง์ ํฉ๋๋ค.
titles: List[str] = ["hello", "world"]
titles.append(100500)
# ERROR: Argument 1 to "hundreds" has incompatible type "str"; expected "Union[int, float]"
titles = ["hello", 1]
# ERROR: List item 1 has incompatible type "int"; expected "str"
items: List = ["hello", 1]
# Everything is good!
์ด ๋ชฉ๋ก์ ๋ถํ์คํ ์๋์ ์ ์ฌํ ํญ๋ชฉ์ด ํฌํจ๋์ด ์๋ค๊ณ ๊ฐ์ ํ์ญ์์ค.๊ทธ๋ฌ๋ ์ฃผ์ ์์์๋ ์ ํ์ด ์์ต๋๋ค. Any
, Optional
, List
๋ฐ ๊ธฐํ ์์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.์์ ์ ํ์ด ์ง์ ๋์ง ์์ผ๋ฉด Any
๋ก ๊ฐ์ ํฉ๋๋ค.
๋ชฉ๋ก ์ธ์ ์ ์ฌํ ์งํฉ ์ฃผ์๋ ์์ต๋๋ค: typing.Set
๊ณผtyping.FrozenSet
.
์ก.๏ธโฃ ๋ค์ค ๊ทธ๋ฃน
๋ชฉ๋ก๊ณผ ๋ฌ๋ฆฌ ๋ฉํ๊ทธ๋ฃน์ ์ผ๋ฐ์ ์ผ๋ก ๋ค๋ฅธ ์ ํ์ ์์์ ์ฌ์ฉ๋ฉ๋๋ค.๋ฌธ๋ฒ์ ๋น์ทํ์ง๋ง ํ ๊ฐ์ง ๋ค๋ฅด๋ค. ์์กฐ์ ๊ฐ ์์์ ์ ํ์ ๊ฐ๊ฐ ๋ค๋ชจ๋ ๊ดํธ๋ก ํ์๋๋ค.
๋ชฉ๋ก๊ณผ ์ ์ฌํ ๋ฉํ๊ทธ๋ฃน์ ์ฌ์ฉํ ๊ณํ์ธ ๊ฒฝ์ฐ ์ ์ ์๋ ์์ ๋์ผํ ์ ํ์ ์์๋ฅผ ์ ์ฅํ๋ ค๋ฉด ์๋ต ๋ฒํธ ...
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ํฐํฐ ์ ํ์ ์ง์ ํ์ง ์๋ ๋ฉ๋ชจTuple
๋ Tuple[Any,ย ...]
์ ๋์ผํ๊ฒ ์๋ํฉ๋๋ค.
price_container: Tuple[int] = (1,)
price_container: ("hello")
# ERROR: Incompatible types in assignment (expression has type "str", variable has type "Tuple[int]")
price_container = (1, 2)
# ERROR: Incompatible types in assignment (expression has type "Tuple[int, int]", variable has type "Tuple[int]")
price_with_title: Tuple[int, str] = (1, "hello")
# Everything is good!
prices: Tuple[int, ...] = (1, 2)
prices: (1,)
prices: (1, "str")
# ERROR: Incompatible types in assignment (expression has type "Tuple[int, str]", variable has type "Tuple[int]")
something: Tuple = (1, 2, "hello")
# Everything is good!
์น .๏ธโฃ ์ฌ์
์ฌ์ typing.Dict
์ ์ฌ์ฉ๋ฉ๋๋ค.ํค ์ ํ๊ณผ ๊ฐ ์ ํ์ ๋ํ ์ค๋ช
์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
book_authors: Dict[str, str] = {"Fahrenheit 451": "Bradbury"}
book_authors["1984"] = 0
# ERROR: Incompatible types in assignment (expression has type "int", target has type "str")
book_authors[1984] = "Orwell"
# ERROR: Invalid index type "int" for "Dict[str, str]"; expected type "str"
์ ์ฌ ์ฌ์ฉtyping.DefaultDict
๋ฐ typing.OrderedDict
ํ.๏ธโฃ ํจ์ ์คํ ๊ฒฐ๊ณผ
๋ชจ๋ ์ข
๋ฅ์ ์ฃผ์์ ํจ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ํ๋ ํ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.ํ์ง๋ง ํน๋ณํ ๊ฒฝ์ฐ๋ ์๋ค.
ํจ์๊ฐ ๊ฒฐ๊ณผ (์: how print
๋ฅผ ๋ฐํํ์ง ์์ผ๋ฉด ๊ฒฐ๊ณผ๋ ํญ์ ๊ฐ์ต๋๋ค None
.์ฐ๋ฆฌ๋ ๋ํ ์ฃผ์None
์ ์ฌ์ฉํ๋ค.
์ด๋ฌํ ํจ์๋ฅผ ์์ฑํ๋ ์ฌ๋ฐ๋ฅธ ์ต์
์ ๋ช
์์ ๋ฐํNone
, ์ง์ ๋์ง ์์ ๊ฐ์ ๋ฐํ ๋ฐ ํธ์ถ๋์ง ์์ ์ข
๋ฃreturn
์
๋๋ค.
def nothing(a: int) -> None:
if a == 1:
return
elif a == 2:
return
elif a == 3:
return "" # No return value expected
else:
pass
ํจ์๊ฐ ์ ์ด๋ฅผ ๋ฐํํ์ง ์๋ ๊ฒฝ์ฐ (์: how sys.exit
๋ฉ๋ชจ NoReturn
๋ฅผ ์ฌ์ฉํฉ๋๋ค.
def forever() -> NoReturn:
while True:
pass
๋ง์ฝ ์ด๊ฒ์ด ์์ฑ ํจ์, ์ฆ ๊ทธ ์ฃผ์ฒด์ ์ฐ์ฐ์ yield๊ฐ ํฌํจ๋์ด ์๋ค๋ฉด, ๋๋์์ค๋ ํจ์Iterable[T]
์ ๋ํด ์ฃผ์Generator[YT, ST, RT]
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
def generate_two() -> Iterable[int]:
yield 1
yield "2"
# ERROR: Incompatible types in "yield" (actual type "str", expected type "int")
๊ฒฐ๋ก ์ด ์๋๋ผ
๋ง์ ๊ฒฝ์ฐ์ ์ ํ ๋ชจ๋์ ์ ๋นํ ์ ํ์ ๊ฐ์ง๊ณ ์์ง๋ง, ๋๋ ๋ชจ๋ ๋ด์ฉ์ ํฌํจํ์ง ์๋๋ค. ์๋ํ๋ฉด ๊ทธ ํ์๋ ๋ฌ์ฌํ ๊ฒ๊ณผ ์ ์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค.์๋ฅผ ๋ค์ด, Iterator
์ collections.abc.Iterator
, typing.SupportsInt
์ ๊ณตํต ๋ฒ์ ์ผ๋ก, ๋์ ์ง์ ๋ฐฉ๋ฒ__int__
๋๋ Callable
์ง์ ๋ฐฉ๋ฒ__call__
์ ํจ์์ ๋์์ ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค
์ด ํ์ค์ ์ ์ ๋ถ์๊ธฐ์ ์ ๋ณด๋ง ํฌํจํ๋ ์ฃผ์๊ณผ ๋ฉ๋ชจ๋ฆฌ ํ์ผ ํ์์ผ๋ก ์ฃผ์์ ํ์์ ์ ์ํ๋ค.
์์ธํ ๋ณด๊ธฐ
์ด ๋ฌธ์๊ฐ ๋์์ด ๋๋ค๋ฉด๐ ๋๋๐ ์๋ ๋ฒํผ์ ๋๋ฅด๊ฑฐ๋ ํ์ด์ค๋ถ์ ์ด ๊ธ์ ๊ณต์ ํ๋ฉด ์น๊ตฌ๋ ์ด์ต์ ๋ณผ ์ ์๋ค.
https://subscribe.to/raevskymichail
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐Python ์ ํ ๋ฉ๋ชจโ๐-โ์ ์๊พธ ์จ์?), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/mikhailraevskiy/python-s-type-annotations-why-you-always-should-use-it-4lh2
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
๋ณ์์ ๋ชฉ๋ก์ด ์์์ ํ์ํ๋ ค๋ฉด ๋ชฉ๋ก ์ ํ์ ์ฃผ์์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.๊ทธ๋ฌ๋ ๋ชฉ๋ก์ ์ด๋ค ์์๊ฐ ํฌํจ๋์ด ์๋์ง ์ง์ ํ๋ ค๋ฉด ์ด๋ฌํ ์ฃผ์์ ๋ ์ด์ ์ ํจํ์ง ์์ต๋๋ค.์ด๋ฅผ ์ํด
typing.List
๊ฐ ์๋ค.์ ํํ ์ ์๋ ๋ณ์ ํ์์ ์ง์ ํ๋ ๋ฐฉ์๊ณผ ์ ์ฌํฉ๋๋ค. ๊ดํธ์ ๋ชฉ๋ก ํญ๋ชฉ์ ํ์์ ์ง์ ํฉ๋๋ค.titles: List[str] = ["hello", "world"]
titles.append(100500)
# ERROR: Argument 1 to "hundreds" has incompatible type "str"; expected "Union[int, float]"
titles = ["hello", 1]
# ERROR: List item 1 has incompatible type "int"; expected "str"
items: List = ["hello", 1]
# Everything is good!
์ด ๋ชฉ๋ก์ ๋ถํ์คํ ์๋์ ์ ์ฌํ ํญ๋ชฉ์ด ํฌํจ๋์ด ์๋ค๊ณ ๊ฐ์ ํ์ญ์์ค.๊ทธ๋ฌ๋ ์ฃผ์ ์์์๋ ์ ํ์ด ์์ต๋๋ค. Any
, Optional
, List
๋ฐ ๊ธฐํ ์์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.์์ ์ ํ์ด ์ง์ ๋์ง ์์ผ๋ฉด Any
๋ก ๊ฐ์ ํฉ๋๋ค.๋ชฉ๋ก ์ธ์ ์ ์ฌํ ์งํฉ ์ฃผ์๋ ์์ต๋๋ค:
typing.Set
๊ณผtyping.FrozenSet
.์ก.๏ธโฃ ๋ค์ค ๊ทธ๋ฃน
๋ชฉ๋ก๊ณผ ๋ฌ๋ฆฌ ๋ฉํ๊ทธ๋ฃน์ ์ผ๋ฐ์ ์ผ๋ก ๋ค๋ฅธ ์ ํ์ ์์์ ์ฌ์ฉ๋ฉ๋๋ค.๋ฌธ๋ฒ์ ๋น์ทํ์ง๋ง ํ ๊ฐ์ง ๋ค๋ฅด๋ค. ์์กฐ์ ๊ฐ ์์์ ์ ํ์ ๊ฐ๊ฐ ๋ค๋ชจ๋ ๊ดํธ๋ก ํ์๋๋ค.
๋ชฉ๋ก๊ณผ ์ ์ฌํ ๋ฉํ๊ทธ๋ฃน์ ์ฌ์ฉํ ๊ณํ์ธ ๊ฒฝ์ฐ ์ ์ ์๋ ์์ ๋์ผํ ์ ํ์ ์์๋ฅผ ์ ์ฅํ๋ ค๋ฉด ์๋ต ๋ฒํธ ...
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ํฐํฐ ์ ํ์ ์ง์ ํ์ง ์๋ ๋ฉ๋ชจTuple
๋ Tuple[Any,ย ...]
์ ๋์ผํ๊ฒ ์๋ํฉ๋๋ค.
price_container: Tuple[int] = (1,)
price_container: ("hello")
# ERROR: Incompatible types in assignment (expression has type "str", variable has type "Tuple[int]")
price_container = (1, 2)
# ERROR: Incompatible types in assignment (expression has type "Tuple[int, int]", variable has type "Tuple[int]")
price_with_title: Tuple[int, str] = (1, "hello")
# Everything is good!
prices: Tuple[int, ...] = (1, 2)
prices: (1,)
prices: (1, "str")
# ERROR: Incompatible types in assignment (expression has type "Tuple[int, str]", variable has type "Tuple[int]")
something: Tuple = (1, 2, "hello")
# Everything is good!
์น .๏ธโฃ ์ฌ์
์ฌ์ typing.Dict
์ ์ฌ์ฉ๋ฉ๋๋ค.ํค ์ ํ๊ณผ ๊ฐ ์ ํ์ ๋ํ ์ค๋ช
์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
book_authors: Dict[str, str] = {"Fahrenheit 451": "Bradbury"}
book_authors["1984"] = 0
# ERROR: Incompatible types in assignment (expression has type "int", target has type "str")
book_authors[1984] = "Orwell"
# ERROR: Invalid index type "int" for "Dict[str, str]"; expected type "str"
์ ์ฌ ์ฌ์ฉtyping.DefaultDict
๋ฐ typing.OrderedDict
ํ.๏ธโฃ ํจ์ ์คํ ๊ฒฐ๊ณผ
๋ชจ๋ ์ข
๋ฅ์ ์ฃผ์์ ํจ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ํ๋ ํ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.ํ์ง๋ง ํน๋ณํ ๊ฒฝ์ฐ๋ ์๋ค.
ํจ์๊ฐ ๊ฒฐ๊ณผ (์: how print
๋ฅผ ๋ฐํํ์ง ์์ผ๋ฉด ๊ฒฐ๊ณผ๋ ํญ์ ๊ฐ์ต๋๋ค None
.์ฐ๋ฆฌ๋ ๋ํ ์ฃผ์None
์ ์ฌ์ฉํ๋ค.
์ด๋ฌํ ํจ์๋ฅผ ์์ฑํ๋ ์ฌ๋ฐ๋ฅธ ์ต์
์ ๋ช
์์ ๋ฐํNone
, ์ง์ ๋์ง ์์ ๊ฐ์ ๋ฐํ ๋ฐ ํธ์ถ๋์ง ์์ ์ข
๋ฃreturn
์
๋๋ค.
def nothing(a: int) -> None:
if a == 1:
return
elif a == 2:
return
elif a == 3:
return "" # No return value expected
else:
pass
ํจ์๊ฐ ์ ์ด๋ฅผ ๋ฐํํ์ง ์๋ ๊ฒฝ์ฐ (์: how sys.exit
๋ฉ๋ชจ NoReturn
๋ฅผ ์ฌ์ฉํฉ๋๋ค.
def forever() -> NoReturn:
while True:
pass
๋ง์ฝ ์ด๊ฒ์ด ์์ฑ ํจ์, ์ฆ ๊ทธ ์ฃผ์ฒด์ ์ฐ์ฐ์ yield๊ฐ ํฌํจ๋์ด ์๋ค๋ฉด, ๋๋์์ค๋ ํจ์Iterable[T]
์ ๋ํด ์ฃผ์Generator[YT, ST, RT]
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
def generate_two() -> Iterable[int]:
yield 1
yield "2"
# ERROR: Incompatible types in "yield" (actual type "str", expected type "int")
๊ฒฐ๋ก ์ด ์๋๋ผ
๋ง์ ๊ฒฝ์ฐ์ ์ ํ ๋ชจ๋์ ์ ๋นํ ์ ํ์ ๊ฐ์ง๊ณ ์์ง๋ง, ๋๋ ๋ชจ๋ ๋ด์ฉ์ ํฌํจํ์ง ์๋๋ค. ์๋ํ๋ฉด ๊ทธ ํ์๋ ๋ฌ์ฌํ ๊ฒ๊ณผ ์ ์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค.์๋ฅผ ๋ค์ด, Iterator
์ collections.abc.Iterator
, typing.SupportsInt
์ ๊ณตํต ๋ฒ์ ์ผ๋ก, ๋์ ์ง์ ๋ฐฉ๋ฒ__int__
๋๋ Callable
์ง์ ๋ฐฉ๋ฒ__call__
์ ํจ์์ ๋์์ ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค
์ด ํ์ค์ ์ ์ ๋ถ์๊ธฐ์ ์ ๋ณด๋ง ํฌํจํ๋ ์ฃผ์๊ณผ ๋ฉ๋ชจ๋ฆฌ ํ์ผ ํ์์ผ๋ก ์ฃผ์์ ํ์์ ์ ์ํ๋ค.
์์ธํ ๋ณด๊ธฐ
์ด ๋ฌธ์๊ฐ ๋์์ด ๋๋ค๋ฉด๐ ๋๋๐ ์๋ ๋ฒํผ์ ๋๋ฅด๊ฑฐ๋ ํ์ด์ค๋ถ์ ์ด ๊ธ์ ๊ณต์ ํ๋ฉด ์น๊ตฌ๋ ์ด์ต์ ๋ณผ ์ ์๋ค.
https://subscribe.to/raevskymichail
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐Python ์ ํ ๋ฉ๋ชจโ๐-โ์ ์๊พธ ์จ์?), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/mikhailraevskiy/python-s-type-annotations-why-you-always-should-use-it-4lh2
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
price_container: Tuple[int] = (1,)
price_container: ("hello")
# ERROR: Incompatible types in assignment (expression has type "str", variable has type "Tuple[int]")
price_container = (1, 2)
# ERROR: Incompatible types in assignment (expression has type "Tuple[int, int]", variable has type "Tuple[int]")
price_with_title: Tuple[int, str] = (1, "hello")
# Everything is good!
prices: Tuple[int, ...] = (1, 2)
prices: (1,)
prices: (1, "str")
# ERROR: Incompatible types in assignment (expression has type "Tuple[int, str]", variable has type "Tuple[int]")
something: Tuple = (1, 2, "hello")
# Everything is good!
์ฌ์
typing.Dict
์ ์ฌ์ฉ๋ฉ๋๋ค.ํค ์ ํ๊ณผ ๊ฐ ์ ํ์ ๋ํ ์ค๋ช
์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.book_authors: Dict[str, str] = {"Fahrenheit 451": "Bradbury"}
book_authors["1984"] = 0
# ERROR: Incompatible types in assignment (expression has type "int", target has type "str")
book_authors[1984] = "Orwell"
# ERROR: Invalid index type "int" for "Dict[str, str]"; expected type "str"
์ ์ฌ ์ฌ์ฉtyping.DefaultDict
๋ฐ typing.OrderedDict
ํ.๏ธโฃ ํจ์ ์คํ ๊ฒฐ๊ณผ
๋ชจ๋ ์ข
๋ฅ์ ์ฃผ์์ ํจ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ํ๋ ํ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.ํ์ง๋ง ํน๋ณํ ๊ฒฝ์ฐ๋ ์๋ค.
ํจ์๊ฐ ๊ฒฐ๊ณผ (์: how print
๋ฅผ ๋ฐํํ์ง ์์ผ๋ฉด ๊ฒฐ๊ณผ๋ ํญ์ ๊ฐ์ต๋๋ค None
.์ฐ๋ฆฌ๋ ๋ํ ์ฃผ์None
์ ์ฌ์ฉํ๋ค.
์ด๋ฌํ ํจ์๋ฅผ ์์ฑํ๋ ์ฌ๋ฐ๋ฅธ ์ต์
์ ๋ช
์์ ๋ฐํNone
, ์ง์ ๋์ง ์์ ๊ฐ์ ๋ฐํ ๋ฐ ํธ์ถ๋์ง ์์ ์ข
๋ฃreturn
์
๋๋ค.
def nothing(a: int) -> None:
if a == 1:
return
elif a == 2:
return
elif a == 3:
return "" # No return value expected
else:
pass
ํจ์๊ฐ ์ ์ด๋ฅผ ๋ฐํํ์ง ์๋ ๊ฒฝ์ฐ (์: how sys.exit
๋ฉ๋ชจ NoReturn
๋ฅผ ์ฌ์ฉํฉ๋๋ค.
def forever() -> NoReturn:
while True:
pass
๋ง์ฝ ์ด๊ฒ์ด ์์ฑ ํจ์, ์ฆ ๊ทธ ์ฃผ์ฒด์ ์ฐ์ฐ์ yield๊ฐ ํฌํจ๋์ด ์๋ค๋ฉด, ๋๋์์ค๋ ํจ์Iterable[T]
์ ๋ํด ์ฃผ์Generator[YT, ST, RT]
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
def generate_two() -> Iterable[int]:
yield 1
yield "2"
# ERROR: Incompatible types in "yield" (actual type "str", expected type "int")
๊ฒฐ๋ก ์ด ์๋๋ผ
๋ง์ ๊ฒฝ์ฐ์ ์ ํ ๋ชจ๋์ ์ ๋นํ ์ ํ์ ๊ฐ์ง๊ณ ์์ง๋ง, ๋๋ ๋ชจ๋ ๋ด์ฉ์ ํฌํจํ์ง ์๋๋ค. ์๋ํ๋ฉด ๊ทธ ํ์๋ ๋ฌ์ฌํ ๊ฒ๊ณผ ์ ์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค.์๋ฅผ ๋ค์ด, Iterator
์ collections.abc.Iterator
, typing.SupportsInt
์ ๊ณตํต ๋ฒ์ ์ผ๋ก, ๋์ ์ง์ ๋ฐฉ๋ฒ__int__
๋๋ Callable
์ง์ ๋ฐฉ๋ฒ__call__
์ ํจ์์ ๋์์ ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค
์ด ํ์ค์ ์ ์ ๋ถ์๊ธฐ์ ์ ๋ณด๋ง ํฌํจํ๋ ์ฃผ์๊ณผ ๋ฉ๋ชจ๋ฆฌ ํ์ผ ํ์์ผ๋ก ์ฃผ์์ ํ์์ ์ ์ํ๋ค.
์์ธํ ๋ณด๊ธฐ
์ด ๋ฌธ์๊ฐ ๋์์ด ๋๋ค๋ฉด๐ ๋๋๐ ์๋ ๋ฒํผ์ ๋๋ฅด๊ฑฐ๋ ํ์ด์ค๋ถ์ ์ด ๊ธ์ ๊ณต์ ํ๋ฉด ์น๊ตฌ๋ ์ด์ต์ ๋ณผ ์ ์๋ค.
https://subscribe.to/raevskymichail
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐Python ์ ํ ๋ฉ๋ชจโ๐-โ์ ์๊พธ ์จ์?), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/mikhailraevskiy/python-s-type-annotations-why-you-always-should-use-it-4lh2
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
def nothing(a: int) -> None:
if a == 1:
return
elif a == 2:
return
elif a == 3:
return "" # No return value expected
else:
pass
def forever() -> NoReturn:
while True:
pass
def generate_two() -> Iterable[int]:
yield 1
yield "2"
# ERROR: Incompatible types in "yield" (actual type "str", expected type "int")
๋ง์ ๊ฒฝ์ฐ์ ์ ํ ๋ชจ๋์ ์ ๋นํ ์ ํ์ ๊ฐ์ง๊ณ ์์ง๋ง, ๋๋ ๋ชจ๋ ๋ด์ฉ์ ํฌํจํ์ง ์๋๋ค. ์๋ํ๋ฉด ๊ทธ ํ์๋ ๋ฌ์ฌํ ๊ฒ๊ณผ ์ ์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค.์๋ฅผ ๋ค์ด,
Iterator
์ collections.abc.Iterator
, typing.SupportsInt
์ ๊ณตํต ๋ฒ์ ์ผ๋ก, ๋์ ์ง์ ๋ฐฉ๋ฒ__int__
๋๋ Callable
์ง์ ๋ฐฉ๋ฒ__call__
์ ํจ์์ ๋์์ ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค์ด ํ์ค์ ์ ์ ๋ถ์๊ธฐ์ ์ ๋ณด๋ง ํฌํจํ๋ ์ฃผ์๊ณผ ๋ฉ๋ชจ๋ฆฌ ํ์ผ ํ์์ผ๋ก ์ฃผ์์ ํ์์ ์ ์ํ๋ค.
์์ธํ ๋ณด๊ธฐ
์ด ๋ฌธ์๊ฐ ๋์์ด ๋๋ค๋ฉด๐ ๋๋๐ ์๋ ๋ฒํผ์ ๋๋ฅด๊ฑฐ๋ ํ์ด์ค๋ถ์ ์ด ๊ธ์ ๊ณต์ ํ๋ฉด ์น๊ตฌ๋ ์ด์ต์ ๋ณผ ์ ์๋ค.
https://subscribe.to/raevskymichail
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐Python ์ ํ ๋ฉ๋ชจโ๐-โ์ ์๊พธ ์จ์?), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/mikhailraevskiy/python-s-type-annotations-why-you-always-should-use-it-4lh2
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐Python ์ ํ ๋ฉ๋ชจโ๐-โ์ ์๊พธ ์จ์?), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://dev.to/mikhailraevskiy/python-s-type-annotations-why-you-always-should-use-it-4lh2ํ ์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค