f_
frhyme.code
•python•โฑ ์•ฝ 9๋ถ„ ์†Œ์š”

Python: static type checking - mypy

Background) Static-type and Dynamic-typed checking

  • python์ด์ „์— ๋น„๊ต์  ์ „ํ†ต์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์— ์†ํ•˜๋Š” c, c++, java ๋“ฑ์˜ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์‹  ๋ถ„๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ต์ˆ™ํ–ˆ์Šต๋‹ˆ๋‹ค.
int a = 10
  • ํ•˜์ง€๋งŒ, ์šฐ๋ฆฌ ์œ„๋Œ€ํ•œ python์˜ ๊ฒฝ์šฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ฃ . ์•„์ฃผ ์งง๊ณ  ๊ฐ„ํŽธํ•ด์ง‘๋‹ˆ๋‹ค.
a = 10
a = "string"
  • ์•ž์— ํ•ด๋‹น variable์˜ type์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๋ ค์ฃผ์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ๊ฒƒ. ์ด ๊ฒƒ์ด ์‚ฌ์†Œํ•œ ์ฐจ์ด์ผ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ด ๊ฐ„ํŽธํ•จ์ด python์ด ์ง€๊ธˆ์ฒ˜๋Ÿผ ๋งŽ์€ ๋Œ€์ค‘๋“ค์—๊ฒŒ ๊ด€์‹ฌ์„ ๋Œ๊ฒŒ ๋œ ์›์ธ ์ค‘ ํ•˜๋‚˜๋ผ๊ณ  ์ €๋Š” ์ƒ๊ฐํ•ด์š”. ํ•˜์ง€๋งŒ, ์œ„์ฒ˜๋Ÿผ ์ฝ”๋“œ๊ฐ€ ์งง๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์ง€๋งŒ, ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง€๊ณ  ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค๊ณผ ์ฝ”๋“œ๊ฐ€ ๊ณต์œ ๋˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด ์ ์ฐจ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒจ ๋‚ฉ๋‹ˆ๋‹ค.

Static-type checking

  • ์•„๋ฌดํŠผ, C์™€ ๊ฐ™์ด, ๋ฏธ๋ฆฌ ๊ฐ โ€™๋ณ€์ˆ˜โ€™์™€ ๋ณ€์ˆ˜๋“ค์„ ์ฒ˜๋ฆฌํ•˜๋Š” โ€™ํ•จ์ˆ˜โ€™๋“ค์— ๋Œ€ํ•ด์„œ ์ฝ”๋“œ ์ž‘์„ฑ์‹œ์— type์ด ์ •์˜๋˜๋Š” ๊ฒƒ์„ ์š”๊ตฌํ•˜๋Š” ์–ธ์–ด๋“ค์„ ์ •์  ํƒ€์ž… ์–ธ์–ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ runtime(์ฝ”๋“œ ์‹คํ–‰) ์ด์ „์ธ ์ปดํŒŒ์ผ ํƒ€์ž„์—์„œ type์„ ์ฒดํฌํ•˜๊ณ  ๋„˜์–ด๊ฐ€๊ฒŒ ๋˜์ฃ . ์ด๋ฅผ ํ†ตํ•ด, ์กฐ๊ธˆ์€ ๋น ๋ฅด๊ฒŒ ํ•ด๋‹น ์ฝ”๋“œ์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์ ๋“ค์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฌผ๋ก , haskell์˜ ๊ฒฝ์šฐ๋Š” ์˜ˆ์™ธ์ ์œผ๋กœ type์„ ๋ฏธ๋ฆฌ ์„ ์–ธํ•˜์ง€ ์•Š๋”๋ผ๋„, ์–ด๋А ์ •๋„๋Š” โ€œํƒ€์ž…์ถ”๋ก โ€์„ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š”, ํ•ด๋‹น โ€œ(ํƒ€์ž…์ด ์•Œ๋ ค์ง€์ง€ ์•Š์€) ๋ณ€์ˆ˜โ€๊ฐ€ โ€œ์–ด๋–ค ํƒ€์ž…์˜ ๋ณ€์ˆ˜์™€ ๊ด€๋ จ๋˜์–ด ์žˆ๋Š”์ง€โ€, ๊ทธ๋ฆฌ๊ณ  โ€œ์–ด๋–ค ํƒ€์ž…์˜ ํ•จ์ˆ˜๋“ค๊ณผ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€โ€๋“ฑ์„ ํ†ตํ•ด ์–ด๋А ์ •๋„๋Š” ํŒŒ์•…ํ•ด๋‚ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•˜๋Š”๋ฐ, ์–ด๋–ค ์˜๋ฏธ์—์„œ, ์ด๋Š” dynamic-type chekcing๊ณผ ์œ ์‚ฌํ•˜๋‹ค๊ณ  ๋А๊ปด์ง€๊ธฐ๋„ ํ•ด์š”(๋‹ค๋งŒ, ์ด ๋ถ€๋ถ„์€ ์ œ ์ •๋ณด๊ฐ€ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋„˜์–ด๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค).
  • ์—ฌ๊ธฐ์— ์†ํ•˜๋Š” ์–ธ์–ด๋“ค๋กœ, C, C++, Go, Haskell, Java, Kotlin, Rust, Scala ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Dynamic-type checking

  • ๋ฐ˜๋Œ€๋กœ python์ฒ˜๋Ÿผ, ๊ฐ ๋ณ€์ˆ˜๋“ค์˜ type์„ ์ •์˜ํ•˜์ง€ ์•Š๊ณ ๋„ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ๋™์ ํƒ€์ž…์–ธ์–ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋ฏธ๋ฆฌ ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— โ€œ๋Œ๋ ค๋ด์•ผ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹คโ€๋ผ๋Š” ๋ง์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ, 1๋ฒˆ ๋Œ๋ฆฌ๋Š”๋ฐ 10์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด, ์ด๋ฅผ dynamic-type์œผ๋กœ ์ฝ”๋”ฉํ•˜์—ฌ, 5์‹œ๊ฐ„์ด ์ง€๋‚œ ๋‹ค์Œ์—์•ผ ์•Œ ์ˆ˜ ์žˆ๋‹ค๋ฉด, ์ข€ ๋ฌด์„ญ๊ฒ ์ฃ ?
  • ์—ฌ๊ธฐ์— ์†ํ•˜๋Š” ์–ธ์–ด๋“ค๋กœ๋Š” python, Ruby, javascript, lisp ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Hybrid type checking

  • python์€ dynamic-type checking ์–ธ์–ด๋กœ ์‹œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค๋งŒ, ์˜ค๋Š˜ ๋งํ• ๊ฒƒ๊ณผ ๊ฐ™์ด, ์ ์  type์„ ๋ฏธ๋ฆฌ ์ง€์ •ํ•˜๋ฉด์„œ ์ฝ”๋”ฉํ•˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๋‚˜์•„๊ฐ€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์˜ ๊ทœ๋ชจ๊ฐ€ ์ปค์ ธ๊ฐ€๋ฉด์„œ ์œ ์ง€๋ณด์ˆ˜ ๋ฌธ์ œ๋กœ ์ธํ•ด์„œ ๊ทธ๋Ÿด ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค, ๋ผ๊ณ  ์ €๋Š” ์ƒ๊ฐ๋˜์–ด์š”. ๋ณดํ†ต, dynamic-type ์—์„œ static-type์œผ๋กœ ๊ฐ€๋Š” ๊ฒฝ์šฐ๋Š” ์ž˜ ์—†์Šต๋‹ˆ๋‹ค.
  • ์กด์žฌํ•˜๋Š” ๋ชจ๋“  ์ฝ”๋“œ์— ๋Œ€ํ•ด์„œ static-type์˜ ํ˜•ํƒœ๋กœ ์ฝ”๋”ฉ๋˜์–ด์•ผ ํ•จ์„ ๊ฐ•์ œํ•˜๋Š” ๊ฒƒ์€ ์ข€ ์–ด๋ ค์šด ์ผ์ด์ฃ . ์ฒ˜์Œ๋ถ€ํ„ฐ ๊ทธ๋ ‡๊ฒŒ ํ–ˆ์œผ๋ฉด ๋ชจ๋ฅผ๊นŒ. ๊ทธ๋ž˜์„œ, ํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„๋งŒ static-type checking์„ ํ†ตํ•ด ๋ถˆํ™•์‹ค์„ฑ์„ ์ค„์ด์ž, ๋ผ๋Š” ๊ฒƒ์ด ์ด๋Ÿฌํ•œ ์„ž์—ฌ ์žˆ๋Š” type checking์ธ ์…ˆ์ด์ฃ .

type conversion

  • implicit type converstion(ํ”„๋กœ๊ทธ๋ž˜๋จธ ๋ชฐ๋ž˜ ์•Œ์•„์„œ ํ˜•์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ)๊ณผ explict type conversion(ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ โ€œ๋ฐ”๊ฟ”!โ€œ๋ผ๊ณ  ํ•˜๋Š” ๊ฒƒ)์œผ๋กœ ๊ตฌ๋ถ„๋ฉ๋‹ˆ๋‹ค. ๋””๋ฒ„๊น…์‹œ์— ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ์—†์• ๋ ค๋ฉด, ๊ฐ€๋Šฅํ•œ explicitํ•œ ๊ฒƒ์ด ๋” ์ข‹๊ธฐ๋Š” ํ•˜์ฃ .

Back to Python: Type hinting

  • ์•„๋ฌดํŠผ, python์œผ๋กœ ๋‹ค์‹œ ๋Œ์•„์™€์„œ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์•ž์„œ ๋งํ•œ ๊ฒƒ์ฒ˜๋Ÿผ python์€ ๋™์  ํƒ€์ž…์–ธ์–ด์ž…๋‹ˆ๋‹ค. ์•„๋ž˜์ฒ˜๋Ÿผ ํƒ€์ž… ์ง€์ •ํ•˜์ง€ ์•Š๊ณ  ์•„๋ฌด ๊ฐ’์ด๋‚˜ ๋ง‰ ์ง‘์–ด๋„ฃ์–ด๋„ ๋˜์ฃ .
var_int = 10
var_str = "33"
var_float = 1.333
  • ํ•˜์ง€๋งŒ, ์ด๋ ‡๊ฒŒ ํ•˜์ง€ ์•Š๊ณ  type์„ ์•Œ๋ ค์ฃผ๋ฉด์„œ ์ฝ”๋”ฉ์„ ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ, type์„ ์•Œ๋ ค์ค„ ๋ฟ, type checking์„ ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์ฆ‰, ๊ทธ๋ƒฅ โ€œ์ฃผ์„โ€๋‹ค๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๊ฐ ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ type์„ ์ ์–ด์ฃผ๋Š” ๊ฒƒ์ด์ฃ . ํ•ด๋‹น ๋‚ด์šฉ์€ PEP-484์— ์ž‘์„ฑ๋˜์–ด ์žˆ์œผ๋ฉฐ, ๊ฐ„๋‹จํ•œ ํ˜•์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. :์„ ์‚ฌ์šฉํ•ด์„œ ๋’ค์— type์„ ์ ์–ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. python native type์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฑฐ์˜ ๋Œ€๋ถ€๋ถ„์˜ type๋“ค, bool/str/int/float/list/dict/tuple์— ๋Œ€ํ•ด์„œ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
# bool/str/int/float/list/dict/tuple
def greeting(param1: str, param2: int) -> str:
    # explicit type conversion for parma2
    return "Hi "+ param1+str(param2) 
########################################
var1: str = "aaa"
var2: int = 1000
var3: float = 14.5
########################################
print(
    greeting(var1, var2)
)
print(
    greeting(var1, var3)
)
  • ์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. python์€ type-hinting, ์ฆ‰ type์ด ๋ฌด์—‡์ธ์ง€ ์ ๊ธฐ๋Š” ํ•˜์ง€๋งŒ, type-checking์„ ํ•˜์ง€๋Š” ์•Š์•„์š”. ๋”ฐ๋ผ์„œ, ์œ„์˜ ํ•จ์ˆ˜์—์„œ param2์—์„œ ์›๋ž˜๋Š”, int๋“ค์–ด์•ผ ํ•˜๋Š”๋ฐ, float์ด ๋“ค์–ด์™€๋„, ๋ฌธ์ œ๊ฐ€ ์—†์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
Hi aaa1000
Hi aaa14.5

mypy: type-checking

  • ํ•˜์ง€๋งŒ, ์šฐ๋ฆฌ๋Š” type-checking์„ ํ•˜๊ณ  ํ”„๋กœ๊ทธ๋žจ์„ ๋Œ๋ฆฌ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” mypy๋ผ๋Š” ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•ด์ค˜์•ผ ํ•˜์ฃ .
  • ์ผ๋‹จ mypy๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
pip install mypy
  • ๊ทธ๋ฆฌ๊ณ , ์•„๋ž˜์™€ ๊ฐ™์ด ํ•ด๋‹น ํŒŒ์ผ์— ๋Œ€ํ•ด์„œ ์ปค๋งจ๋“œ๋ผ์ธ์—์„œ ๋Œ๋ ค๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.
mypy test.py
  • ๊ฐ„๋‹จํ•˜์ง€๋งŒ, ์˜ค๋ฅ˜๋ฅผ ์žก์•„์คฌ์ฃ .
test.py:29: error: Argument 2 to "greeting" has incompatible type "float"; expected "int"
Found 1 error in 1 file (checked 1 source file)

wrap-up

  • ์‚ฌ์‹ค ์ฒ˜์Œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๋ฐฐ์šธ ๋•Œ๋Š” dynamic-type์ด ํŽธํ•˜์ง€๋งŒ, ์‹œ๊ฐ„์ด ๊ฐˆ์ˆ˜๋ก ์–ด๋А ์ •๋„๋Š” static์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ๋ฅผ ๋ฐ”๋ž„ ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šค์Šค๋กœ๋ฅผ ๋ฏฟ์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋‚˜์˜ ์‹ค์ˆ˜๋ฅผ ๋ฏธ๋ฆฌ ๋ง‰์•„์ค„ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ผ๋Š” ๋งˆ์Œ๋„ ์žˆ๊ณ ์š”.
  • static type์œผ๋กœ ์ฒ˜๋ฆฌํ•  ๋•Œ์˜ ๊ฐ•์ ์ด๋ผ๋ฉด, ์•„๋‹ˆ, ์ตœ์†Œํ•œ annotation์œผ๋กœ ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜์˜ ํƒ€์ž…์„ ์ •์˜ํ•˜๋ฉด์„œ ์ฝ”๋”ฉํ•  ๋•Œ์˜ ๊ฐ•์ ์ด๋ผ๋ฉด, ๊ทธ ํ•จ์ˆ˜์˜ ํŒŒ์ดํ”„๋ผ์ธ์ด ์–ด๋–ค ํ˜•ํƒœ๋กœ ๋˜๋Š”์ง€, ๋Œ€๋žต์€ ๊ตฌ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด์ฃ . ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ ๋‘ ํ•จ์ˆ˜๋ฅผ ๋ณธ๋‹ค๋ฉด, type-hinting์„ ํ• ๋•Œ โ€œ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑโ€์ด ์ƒ๋‹นํžˆ ์˜ฌ๋ผ๊ฐ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋ฌผ๋ก  ๋ณ€์ˆ˜๋ช…์„ ์‚ฌ์šฉํ•ด์„œ type hinting์„ ํ•  ์ˆ˜๋„ ์žˆ๊ธด ํ•ฉ๋‹ˆ๋‹ค๋งŒ)
def func_without_typehinting(a, b, c, d):
    return [ str(a)+str(b)+x+c for x in d]
def func_with_typehinting(a:int, b:float, c:str, d:list):
    return [ str(a)+str(b)+x+c for x in d]
  • ๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ, ์ €๋ ‡๊ฒŒ ์จ์ค€๋‹ค๊ณ  ํ•ด์„œ, python์„ ์‹คํ–‰์‹œํ‚ฌ ๋•Œ ์•Œ์•„์„œ type์„ ์žก์•„์ฃผ๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„, โ€œ์ œ๊ฐ€ ์ง์ ‘ static-type checking์„ ํ•  ์ˆ˜ ์žˆ๋‹คโ€๋ผ๋Š” ๊ฒƒ์ด ํฌ๊ณ , ์ด๋กœ ์ธํ•ด ์ฝ”๋“œ์˜ ๋ฒ„๊ทธ๋ฅผ ์ƒ๋‹นํžˆ ์ค„์ผ ์ˆ˜ ์žˆ๊ฒ ์ฃ .
  • ๋ฌผ๋ก , ๋‹ค์‹œ ์ƒ๊ฐํ•ด๋ณธ๋‹ค๋ฉด, python์œผ๋กœ ์ฝ”๋”ฉํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋Œ€๋ถ€๋ถ„ ๋ฐ์ดํ„ฐ ๋ถ„์„์„ ๋ชฉ์ ์œผ๋กœ ํ• ๋•Œ ์ด๊ณ , ์ด ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” numpy, pandas๋“ฑ์˜ ๊ฒฝ์šฐ๋Š” ์ด๋ฏธ dtype๋“ค์ด ์ง€์ •๋œ ์ƒํƒœ๋กœ ์ง„ํ–‰๋˜์ฃ . ์ด๋ ‡๊ฒŒ ์ƒ๊ฐํ•˜๋‹ˆ, ๋˜ ๊ตณ์ด, type์„ ์„ ์–ธํ•ด์ฃผ๋Š” ๊ฒŒ ํ•„์š”ํ•œ๊ฐ€ ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค๊ธฐ๋„ ํ•˜๋„ค์š”.

reference

๐Ÿ’กRELATED ARTICLES ยท ํ•จ๊ป˜ ์ฝ์œผ๋ฉด ์ข‹์€ ์—ฐ๊ด€ ํฌ์ŠคํŠธ

๊ธ€ ์ฃผ์†Œ๊ฐ€ ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.