From 39284cce3eed69adc328a4389e20a28fef157219 Mon Sep 17 00:00:00 2001 From: DONG GUN LEE Date: Wed, 11 Sep 2024 01:03:23 +0900 Subject: [PATCH] =?UTF-8?q?[8ee3431]=20=EB=B2=88=EC=97=AD=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=F0=9F=92=AC=20(#37)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * merge 8ee3431 ๐Ÿ›ฐ * [8ee3431] 1.1 ๋ฐฐ๊ฒฝ ๋ฐ˜์˜ * [8ee3431] 2.1 Lint ๋ฐ˜์˜ * [8ee3431] 2.2 import ๋ฐ˜์˜ * [8ee3431] 2.3 package ๋ฐ˜์˜ * [8ee3431] 2.4 ์˜ˆ์™ธ์ฒ˜๋ฆฌ ๋ฐ˜์˜ * [8ee3431] 2.5 ์ด๋ฆ„ ๋ณ€๊ฒฝ * [8ee3431] 2.5 ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ ๋ฐ˜์˜ * [8ee3431] 2.6 ์ค‘์ฒฉ ๋ฐ˜์˜ * [8ee3431] 2.7 list comprehensions * [8ee3431] 2.8 ๊ธฐ๋ณธ ๋ฐ˜๋ณต์ž์™€ ์—ฐ์‚ฐ์ž ๋ฐ˜์˜ * [8ee3431] 2.9 ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๋ฐ˜์˜ * [8ee3431] 2.10 ๋žŒ๋‹ค ๋ฐ˜์˜ * [8ee3431] 2.12 ๊ธฐ๋ณธ ์ธ์ž ๊ฐ’ ๋ฐ˜์˜ * [8ee3431] 2.14 True/False ํ‰๊ฐ€ ๋ฐ˜์˜ * [8ee3431] 2.16 ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ•‘ ๋ฐ˜์˜ * [8ee3431] 2.17 ํ•จ์ˆ˜์™€ ๋ฉ”์„œ๋“œ ๋ฐ˜์˜ * [8ee3431] 2.18 ์Šค๋ ˆ๋“œ ๋ฐ˜์˜ * [8ee3431] 2.20 ํ˜„๋Œ€์˜ ํŒŒ์ด์ฌ ๋ฐ˜์˜ * [8ee3431] 2.20 ์ด๋ฆ„ ๋ณ€๊ฒฝ * [8ee3431] 2.21 Type ์ฃผ์„ ๋ฐ˜์˜ * [8ee3431] 3.2 ์ค„ ๊ธธ์ด ๋ฐ˜์˜ * [8ee3431] 3.4 ๋“ค์—ฌ์“ฐ๊ธฐ ๋ฐ˜์˜ * [8ee3431] 3.5 ๋นˆ ์ค„ ๋ฐ˜์˜ * [8ee3431] 3.7 Shebang_Line ๋ฐ˜์˜ * [8ee3431] 3.8 ์ฃผ์„๊ณผ docstring ๋ฐ˜์˜ * [8ee3431] 3.10 ๋ฌธ์ž์—ด ๋ฐ˜์˜ * [8ee3431] 3.12 TODO ์ฃผ์„ ๋ฐ˜์˜ * [8ee3431] 3.13 import ํ˜•์‹ ๋ฐ˜์˜ * [8ee3431] 3.16 ๋„ค์ด๋ฐ ๋ฐ˜์˜ * [8ee3431] 3.19 Type ์ฃผ์„ ๋ฐฉ๋ฒ• ๋ฐ˜์˜ * [8ee3431] 4.1 ๋งบ์Œ๋ง ๋ฐ˜์˜ * ๋นŒ๋“œ ๊ฒฝ๊ณ  ์ˆ˜์ • * ๋นŒ๋“œ ๊ฒฝ๊ณ  ์ˆ˜์ • * [8ee3431] build --- Google Python Style Guide kor.md | 900 ++++++++------ .../1.1 \353\260\260\352\262\275.md" | 2 +- .../1. \353\260\260\352\262\275/ReadMe.md" | 2 +- .../2.1 Lint.md" | 7 +- .../2.10 \353\236\214\353\213\244.md" | 4 +- ... \354\235\270\354\236\220 \352\260\222.md" | 11 +- ...4 True, False \355\217\211\352\260\200.md" | 2 +- ...4\275\224\355\225\221(Lexical Scoping).md" | 2 +- ...224\354\204\234\353\223\234 Decorators.md" | 4 +- ...8 \354\212\244\353\240\210\353\223\234.md" | 2 +- .../2.2 import.md" | 22 +- .../2.20 Modern Python.md" | 18 - .../2.21 Type \354\243\274\354\204\235.md" | 14 +- .../2.3 package.md" | 4 +- ...10\354\231\270\354\262\230\353\246\254.md" | 11 +- ...4\354\227\255 \354\203\201\355\203\234.md" | 40 + ...04\354\227\255\353\263\200\354\210\230.md" | 34 - .../2.6 \354\244\221\354\262\251.md" | 2 +- .../2.7 list_comprehensions.md" | 53 +- ...0 \354\227\260\354\202\260\354\236\220.md" | 6 +- ...10\353\240\210\354\235\264\355\204\260.md" | 4 +- .../ReadMe.md" | 192 ++- ...0 \353\254\270\354\236\220\354\227\264.md" | 18 +- .../3.12 TODO \354\243\274\354\204\235.md" | 31 +- .../3.13 import\355\230\225\354\213\235.md" | 20 +- ...6 \353\204\244\354\235\264\353\260\215.md" | 27 +- ...4\354\204\235 \353\260\251\353\262\225.md" | 298 +++-- ... \354\244\204 \352\270\270\354\235\264.md" | 83 +- ...44\354\227\254\354\223\260\352\270\260.md" | 34 +- .../3.5 \353\271\210 \354\244\204.md" | 2 +- .../3.7 Shebang_Line.md" | 2 +- ...\274\354\204\235\352\263\274 docstring.md" | 177 ++- .../ReadMe.md" | 691 +++++++---- ...1 \353\247\272\354\235\214\353\247\220.md" | 9 +- .../ReadMe.md" | 9 +- Original.md | 1032 ++++++++++------- script/build.py | 4 +- 37 files changed, 2329 insertions(+), 1444 deletions(-) rename "Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.20 \355\230\204\353\214\200\354\235\230 \355\214\214\354\235\264\354\215\254.md" => "Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.20 Modern Python.md" (58%) create mode 100644 "Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.5 \353\263\200\352\262\275 \352\260\200\353\212\245\355\225\234 \354\240\204\354\227\255 \354\203\201\355\203\234.md" delete mode 100644 "Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.5 \354\240\204\354\227\255\353\263\200\354\210\230.md" diff --git a/Google Python Style Guide kor.md b/Google Python Style Guide kor.md index 68e036b..eb466a1 100644 --- a/Google Python Style Guide kor.md +++ b/Google Python Style Guide kor.md @@ -9,7 +9,7 @@ * [2.2 Imports](#s2.2-imports) * [2.3 Packages](#s2.3-packages) * [2.4 ์˜ˆ์™ธ](#s2.4-exceptions) - * [2.5 ์ „์—ญ ๋ณ€์ˆ˜](#s2.5-global-variables) + * [2.5 ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ](#25-global-state) * [2.6 ์ค‘์ฒฉ/์ง€์—ญ/๋‚ด๋ถ€ ํด๋ž˜์Šค์™€ ํ•จ์ˆ˜](#s2.6-nested) * [2.7 Comprehensions & ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ‘œํ˜„์‹](#s2.7-list_comprehensions) * [2.8 ๊ธฐ๋ณธ ๋ฐ˜๋ณต์ž์™€ ์—ฐ์‚ฐ์ž](#s2.8-default-iterators-and-operators) @@ -67,8 +67,8 @@ + [3.19.7 Ignoring Types](#s3.19.7-ignore) + [3.19.8 ๋‚ด๋ถ€ ๋ณ€์ˆ˜ ์ž‘์„ฑ](#s3.19.8-comments) + [3.19.9 ํŠœํ”Œ vs ๋ฆฌ์ŠคํŠธ](#s3.19.9-tuples) - + [3.19.10 TypeVar](#s3.19.10-type-var) - + [3.19.11 ๋ฌธ์ž์—ด Type](#s3.19.11-strings) + + [3.19.10 Type variables](#typevars) + + [3.19.11 ๋ฌธ์ž์—ด Type](#typing-strings) + [3.19.12 Typing ์ถ”๊ฐ€](#s3.19.12-imports) + [3.19.13 ์กฐ๊ฑด Imports](#s3.19.13-conditional-imports) + [3.19.14 Circular ์ข…์†](#s3.19.14-circular-deps) @@ -87,7 +87,7 @@ - ์ด ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ๋Š” Python ํ”„๋กœ๊ทธ๋žจ์—์„œ _ํ•ด์•ผ ํ•  ๊ฒƒ๋“ค๊ณผ ํ•˜์ง€ ๋ง์•„์•ผ ํ•  ๊ฒƒ_ ๋“ค์„ ์ ์–ด๋†“์•˜์Šต๋‹ˆ๋‹ค. - ์ฝ”๋“œ ํ˜•์‹์„ ์ •ํ™•ํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ๋“ค ๋•๊ธฐ ์œ„ํ•ด, ์šฐ๋ฆฌ๋Š” [settings file for Vim](google_python_style.vim)์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. - Emacs ํŽธ์ง‘๊ธฐ์—์„œ๋Š” ๊ธฐ๋ณธ ์„ค์ •๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. -- ๋งŽ์€ ํŒ€์—์„œ ํ˜•์‹์— ๋Œ€ํ•œ ๋…ผ์Ÿ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด [yapf](https://github.com/google/yapf/) auto-formatter ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +- ๋งŽ์€ ํŒ€์—์„œ ํ˜•์‹์— ๋Œ€ํ•œ ๋…ผ์Ÿ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด [Black](https://github.com/psf/black) ํ˜น์€ [Pyink](https://github.com/google/pyink) auto-formatter ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. --- @@ -137,7 +137,8 @@ - ๊ฒฝ๊ณ ๋ฅผ ๋„์šฐ์ง€ ์•Š๊ธฐ ์œ„ํ•ด, ์ฝ”๋“œ์— ๋ผ์ธ ๋‹จ์œ„๋กœ ์ฃผ์„์„ ๋‹ฌ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ```python - dict = 'something awful' # Bad Idea... pylint: disable=redefined-builtin + def do_PUT(self): # WSGI name, so pylint: disable=invalid-name + ... ``` - `pylint`์˜ ๊ฒฝ๊ณ ๋Š” ๊ฐ๊ฐ symbolic name(`empty-docstring`)์œผ๋กœ ๊ตฌ๋ณ„๋ฉ๋‹ˆ๋‹ค. @@ -153,7 +154,7 @@ - ๊ฐ ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•ด ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ์–ป๊ณ ์ž ํ•˜๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```shell - pylint --help-msg=C6409 + pylint --help-msg=invalid-name ``` - `pyling: disable-msg`๋Š” ์ด์ „์— ์‚ฌ์šฉํ–ˆ๋˜ ๋ฐฉ์‹์œผ๋กœ ์ด์ œ๋Š” ์‚ฌ์šฉ๋˜์ง€ ์•Š์œผ๋ฉฐ `pylint: disable`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. @@ -161,7 +162,7 @@ - ์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. ```python - def viking_cafe_order(spam: str, beans: str, eggs: Optional[str] = None) -> str: + def viking_cafe_order(spam: str, beans: str, eggs: str | None = None) -> str: del beans, eggs # Unused by vikings. return spam + spam + spam ``` @@ -173,7 +174,7 @@ ### 2.2 Imports -- `import`๋ฌธ์„ ์‚ฌ์šฉํ• ๋•Œ package์™€ module์— ์‚ฌ์šฉํ•˜๊ณ  ๊ฐœ๋ณ„ ํด๋ž˜์Šค๋‚˜ ํ•จ์ˆ˜์— ๋Œ€ํ•ด ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ [typing ๋ชจ๋“ˆ](#s3.19.12-imports), [typing_extensions module](https://github.com/python/typing/tree/master/typing_extensions)์—์„œ ๊ฐ€์ ธ์˜จ ํด๋ž˜์Šค ๋ฐ [six.moves module](https://six.readthedocs.io/#module-six.moves)์—์„œ์˜ ๋ฆฌ๋””๋ ‰์…˜์€ ์ด ๊ทœ์น™์—์„œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค. +- `import`๋ฌธ์€ ๊ฐœ๋ณ„ ํƒ€์ž…, ํด๋ž˜์Šค, ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ ํŒจํ‚ค์ง€์™€ ๋ชจ๋“ˆ์—๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”. (์ฃผ: ๊ฐœ๋ณ„ ํƒ€์ž…์€ ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•, ์‚ฌ์šฉ์ž ์ •์˜ ํด๋ž˜์Šค๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.) @@ -199,8 +200,13 @@ - `import x`๋ฅผ ํŒจํ‚ค์ง€์™€ ๋ชจ๋“ˆ์„ importํ• ๋•Œ ์‚ฌ์šฉํ•˜์„ธ์š”. - `from x import y`๋ฅผ `x`๊ฐ€ ํŒจํ‚ค์ง€์˜ ์ ‘๋‘์–ด์ด๊ณ  `y`๊ฐ€ ์ ‘๋‘์–ด๊ฐ€ ์—†๋Š” ๋ชจ๋“ˆ์ผ๋•Œ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ๋งŒ์•ฝ `y` ๋กœ ์ด๋ฆ„์ด ์ง€์–ด์ง„ ๋‘ ๋ชจ๋“ˆ์ด import๋˜๊ฑฐ๋‚˜ `y` ๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋„ˆ๋ฌด ๊ธด ์ด๋ฆ„์„ ๊ฐ€์กŒ๋‹ค๋ฉด `from x import y as z`๋ฅผ ์‚ฌ์šฉ์„ธ์š”. -- `import y as z`๋ฅผ `z` ๊ฐ€ ๊ณต์‹์ ์ธ ์•ฝ์–ด์ธ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”(e.g., `np` ๋Š” `numpy` ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.) +- ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ๋Š” `from x import y as z` ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + - `y`๋ผ๋Š” ์ด๋ฆ„์„ ๊ฐ€์ง„ ๋‘ ๊ฐœ์˜ ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. + - `y`๋Š” ํ˜„์žฌ ๋ชจ๋“ˆ์— ์ •์˜๋œ ์ตœ์ƒ์œ„ ์ด๋ฆ„๊ณผ ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค. + - `y`๋Š” ๊ณต๊ฐœ API์˜ ์ผ๋ถ€์ธ ๊ณตํ†ต ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„(์˜ˆ: 'features')๊ณผ ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค. + - `y`๋Š” ๋ถˆํŽธํ•  ์ •๋„๋กœ ๊ธด ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. + - `y`๋Š” ์ฝ”๋“œ ์ปจํ…์ŠคํŠธ์—์„œ ๋„ˆ๋ฌด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค(์˜ˆ: `from storage.file_system import options as fs_options`). +- `import y as z`๋ฅผ `z` ๊ฐ€ ๊ณต์‹์ ์ธ ์•ฝ์–ด์ธ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”(e.g., `import numpy as np`) - ์˜ˆ๋ฅผ๋“ค์–ด `sound.effects.echo`๋ชจ๋“ˆ์ด import ๋œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -214,6 +220,17 @@ - ๋ชจ๋“ˆ์ด ๊ฐ™์€ ํŒจํ‚ค์ง€์— ์žˆ๋”๋ผ๋„ ์ „์ฒด ํŒจํ‚ค์ง€ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์„ธ์š”. - ์ด๋Š” ๋ฌด์‹ฌ์ฝ” ํŒจํ‚ค์ง€๋ฅผ ๋‘๋ฒˆ import ํ•˜๋Š”๊ฒƒ์„ ์˜ˆ๋ฐฉํ•˜๋Š” ๊ฒƒ์— ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. + + +##### 2.2.4.1 ์˜ˆ์™ธ + +- ์ด ๊ทœ์น™์˜ ์˜ˆ์™ธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. + - ๋‹ค์Œ ๋ชจ๋“ˆ์˜ ์‹ฌ๋ณผ์€ ์ •์  ๋ถ„์„ ๋ฐ ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ์ง€์›ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + - [`typing` module](#typing-imports) + - [`collections.abc` module](#typing-imports) + - [`typing_extensions` module](https://github.com/python/typing_extensions/blob/main/README.md) + - [six.moves module](https://six.readthedocs.io/#module-six.moves)์˜ ๋ฆฌ๋‹ค์ด๋ ‰์…˜์ž…๋‹ˆ๋‹ค. + --- @@ -248,7 +265,7 @@ import absl.flags from doctor.who import jodie - FLAGS = absl.flags.FLAGS + _FOO = absl.flags.DEFINE_string(...) ``` ```python @@ -256,7 +273,7 @@ from absl import flags from doctor.who import jodie - FLAGS = flags.FLAGS + _FOO = flags.DEFINE_string(...) ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ _(์ด ํŒŒ์ผ์€ `doctor/who/` ์— ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  `jodie.py`๋˜ํ•œ ์กด์žฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.)_ @@ -304,10 +321,8 @@ ##### ์˜ˆ์™ธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค -- ์ ์ ˆํ•œ ๊ฒฝ์šฐ ๋‚ด์žฅ ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ์˜ˆ๋ฅผ ๋“ค์–ด, ๋งŒ์•ฝ ์–‘์ˆ˜๋ฅผ ์˜ˆ์ƒํ•˜๋Š”๋ฐ ์Œ์ˆ˜๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค๋ฉด `ValueError`๋ฅผ ๋ฐœ์ƒ์‹œ๋Š” ๊ฒƒ์ด ๊ทธ ์˜ˆ์ž…๋‹ˆ๋‹ค. -- ๊ณต๊ณต API์— ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฐ’์„ ๊ฒ€์ฆํ•˜๊ธฐ ์œ„ํ•ด `assert`๋ฌธ์„ ์‚ฌ์šฉํ•˜์ง€๋งˆ์„ธ์š”. -- `assert`๋Š” ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ์ด๋‚˜ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์ด๋ฒคํŠธ ๋ฐœ์ƒ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋‚ด๋ถ€์  ์ •ํ™•์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋‚˜์ค‘์— ์˜ˆ์™ธ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด, raise๋ฌธ์„ ์‹คํ–‰ํ•˜์„ธ์š”. +- ๋‚ด์žฅ ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์— ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋ฉด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•จ์ˆ˜ ์ธ์ž๋ฅผ ๊ฒ€์ฆํ•  ๋•Œ์™€ ๊ฐ™์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์˜ค๋ฅ˜๋‚˜ ์œ„๋ฐ˜๋œ ์ „์ œ์กฐ๊ฑด์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด `ValueError`๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์„ธ์š”. +- `assert` ๋ฌธ์„ ์กฐ๊ฑด๋ฌธ์ด๋‚˜ ์ „์ œ์กฐ๊ฑด ๊ฒ€์ฆ ๋Œ€์‹  ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. application logic์— ์ค‘์š”ํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. `assert`๋ฌธ์„ ์ œ๊ฑฐํ•ด๋„ ์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•œ๋‹ค๋ฉด, ๊ทธ๊ฒƒ์ด ๊ธฐ์ค€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. assert ์กฐ๊ฑด๋ฌธ์€ ํ‰๊ฐ€๋  ๊ฒƒ์ด๋ผ๊ณ  [๋ณด์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค](https://docs.python.org/3/reference/simple_stmts.html#the-assert-statement). [pytest](https://pytest.org)๊ธฐ๋ฐ˜์˜ ํ…Œ์ŠคํŠธ์—์„œ๋Š” `assert` ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋Œ€๊ฐ’์„ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ์ด ์ ์ ˆํ•˜๊ณ  ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -326,9 +341,10 @@ if minimum < 1024: raise ValueError(f'Min. port must be at least 1024, not {minimum}.') port = self._find_next_open_port(minimum) - if not port: + if port is None: raise ConnectionError( f'Could not connect to service on port {minimum} or higher.') + # ์ด ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ๋Š” ์ด assert์— ์˜์กดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. assert port >= minimum, ( f'Unexpected port {port} when minimum was {minimum}.') return port @@ -346,8 +362,10 @@ The new minimum port. """ assert minimum >= 1024, 'Minimum port must be at least 1024.' + # ์ด ์ฝ”๋“œ๋Š” ์ด์ „ assert์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. port = self._find_next_open_port(minimum) assert port is not None + # ๋ฐ˜ํ™˜ ๊ฐ’์— ๋Œ€ํ•œ ํƒ€์ž… ๊ฒ€์‚ฌ๋Š” assert์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. return port ``` @@ -360,16 +378,19 @@ --- + + + -### 2.5 ์ „์—ญ ๋ณ€์ˆ˜ +### 2.5 ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ -- ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. +- ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. #### 2.5.1 ์ •์˜ -- ๋ชจ๋“ˆ์ด๋‚˜ ํด๋ž˜์Šค ์†์„ฑ์œผ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค. +- ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์ค‘ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“ˆ ์ˆ˜์ค€์˜ ๊ฐ’์ด๋‚˜ ํด๋ž˜์Šค ์†์„ฑ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. @@ -378,21 +399,24 @@ - ๊ฐ€๋” ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + + #### 2.5.3 ๋‹จ์  -- import๋˜๋Š” ๋™์•ˆ ๋ชจ๋“ˆ์˜ ๋™์ž‘์ด ๋ณ€๊ฒฝ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ „์—ญ ๋ณ€์ˆ˜์˜ ํ• ๋‹น์€ ๋ชจ๋“ˆ์„ ์ฒ˜์Œ import๋ฅผ ํ• ๋•Œ ์ˆ˜ํ–‰์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +- ์บก์Šํ™”๊ฐ€ ๊นจ์ง‘๋‹ˆ๋‹ค. + - ์ด๋Ÿฌํ•œ ์„ค๊ณ„๋Š” ์œ ํšจํ•œ ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด, ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ, ๋‘ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋™์‹œ์— ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(e.g., ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ค‘ ์ฐจ์ด๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ). ์ „์—ญ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์—์„œ๋„ ์œ ์‚ฌํ•œ ๋ฌธ์ œ๊ฐ€ ์‰ฝ๊ฒŒ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- ๋ชจ๋“ˆ์ด ์ฒ˜์Œ ์ž„ํฌํŠธ๋  ๋•Œ ์ „์—ญ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ํ• ๋‹น์ด ์ด๋ฃจ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์—, ๋ชจ๋“ˆ์˜ ๋™์ž‘์„ ์ž„ํฌํŠธ ์ค‘์— ๋ณ€๊ฒฝํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + + #### 2.5.4 ๊ฒฐ๋ก  -- ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. - -- ์ „์—ญ๋ณ€์ˆ˜๋Š” ๊ธฐ์ˆ ์ ์œผ๋กœ๋Š” ๋ณ€์ˆ˜์ด์ง€๋งŒ, module-level ์ƒ์ˆ˜๊ฐ€ ํ—ˆ์šฉ๋˜๊ณ  ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. -- ์˜ˆ๋ฅผ๋“ค์–ด `_MAX_HOLY_HANDGRENADE_COUNT = 3`. ์ƒ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ๋ชจ๋“  ๊ณต๋ฐฑ `_`๋ฅผ ๋„ฃ์–ด์„œ ์ด๋ฆ„์„ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋งŒ์•ฝ ์ „์—ญ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด module-level์—์„œ ์„ ์–ธ๋˜๊ณ  ๋ชจ๋“ˆ ๋‚ด๋ถ€์—์„œ ์ด๋ฆ„์— `_`๋ฅผ ๋ถ™์—ฌ์„œ ๋งŒ๋“ค์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์™ธ๋ถ€ ์ ‘๊ทผ์€ ๋ฐ˜๋“œ์‹œ public๋‹จ์œ„์˜ module-level ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ ๋™์ž‘๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. [Naming](#s3.16-naming)์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. +- ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. + - ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋“œ๋ฌผ๊ฒŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์—”ํ‹ฐํ‹ฐ๋Š” ๋ชจ๋“ˆ ์ˆ˜์ค€์ด๋‚˜ ํด๋ž˜์Šค ์†์„ฑ์œผ๋กœ ์„ ์–ธํ•˜๊ณ , ์ด๋ฆ„ ์•ž์— `_`๋ฅผ ๋ถ™์—ฌ ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ์— ๋Œ€ํ•œ ์™ธ๋ถ€ ์ ‘๊ทผ์€ ๊ณต๊ฐœ ํ•จ์ˆ˜๋‚˜ ํด๋ž˜์Šค ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. [Naming](#s3.16-naming)๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์„ค๊ณ„ ์ด์œ ์— ๋Œ€ํ•ด์„œ๋Š” ์ฃผ์„์— ์„ค๋ช…ํ•˜๊ฑฐ๋‚˜ ๋งํฌ๋œ ๋ฌธ์„œ์—์„œ ์„ค๋ช…ํ•ด ์ฃผ์„ธ์š”. + - ๋ชจ๋“ˆ ์ˆ˜์ค€์˜ ์ƒ์ˆ˜๋Š” ํ—ˆ์šฉ๋˜๋ฉฐ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‚ด๋ถ€ ์šฉ๋„์˜ ์ƒ์ˆ˜์—๋Š” `_MAX_HOLY_HANDGRENADE_COUNT = 3`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , Public API ์ƒ์ˆ˜์—๋Š” `SIR_LANCELOTS_FAVORITE_COLOR = "blue"`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ƒ์ˆ˜๋Š” ๋ชจ๋‘ ๋Œ€๋ฌธ์ž์™€ ๋ฐ‘์ค„์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…๋ช…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. [Naming](#s3.16-naming)๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. --- @@ -415,7 +439,7 @@ #### 2.6.2 ์žฅ์  - ์ œํ•œ๋œ ์Šค์ฝ”ํ”„ ๋‚ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค์™€ ํ•จ์ˆ˜์˜ ์ •์˜๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. -- [ADT](http://www.google.com/url?sa=D&q=http://en.wikipedia.org/wiki/Abstract_data_type)๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ฐธ๊ณ ํ•˜์„ธ์š”. +- [ADT](https://ko.wikipedia.org/wiki/์ถ”์ƒ_์ž๋ฃŒํ˜•)๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ฐธ๊ณ ํ•˜์„ธ์š”. - ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. @@ -464,19 +488,17 @@ #### 2.7.4 ๊ฒฐ๋ก  -- ๋ณต์žกํ•˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ฐ๊ฐ์˜ ๋ถ€๋ถ„์€ ๋ฐ˜๋“œ์‹œ ํ•œ ๋ผ์ธ์—์„œ ๋๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- map, for๋ฌธ, filter ํ‘œํ˜„์‹์ด ๊ทธ ์˜ˆ์ž…๋‹ˆ๋‹ค. ์ค‘์ฒฉ for๋ฌธ์ด๋‚˜ filter๋ฌธ์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -- loop๋ฌธ์„ ํ†ตํ•ด ์ฝ”๋“œ๋ฅผ ๋‹จ์ˆœํ™” ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์ปดํ”„๋ฆฌํ—จ์…˜(comprehension)์€ ํ—ˆ์šฉ๋˜์ง€๋งŒ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ for ์ ˆ์ด๋‚˜ ํ•„ํ„ฐ ํ‘œํ˜„์‹์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ„๊ฒฐํ•จ๋ณด๋‹ค๋Š” ๊ฐ€๋…์„ฑ์„ ์šฐ์„ ์‹œํ•˜์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python result = [mapping_expr for value in iterable if filter_expr] - result = [{'key': value} for value in iterable - if a_long_filter_expression(value)] - - result = [complicated_transform(x) - for x in iterable if predicate(x)] + result = [ + is_valid(metric={'key': value}) + for value in interesting_iterable + if a_longer_filter_expression(value) + ] descriptive_name = [ transform({'key': key, 'value': value}, color='black') @@ -486,37 +508,32 @@ result = [] for x in range(10): - for y in range(5): - if x * y > 10: - result.append((x, y)) - - return {x: complicated_transform(x) - for x in long_generator_function(parameter) - if x is not None} - - squares_generator = (x**2 for x in range(10)) + for y in range(5): + if x * y > 10: + result.append((x, y)) + return { + x: complicated_transform(x) + for x in long_generator_function(parameter) + if x is not None + } + return (x**2 for x in range(10)) unique_names = {user.name for user in users if user is not None} - - eat(jelly_bean for jelly_bean in jelly_beans - if jelly_bean.color == 'black') ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - result = [complicated_transform( - x, some_argument=x+1) - for x in iterable if predicate(x)] - result = [(x, y) for x in range(10) for y in range(5) if x * y > 10] - return ((x, y, z) - for x in range(5) - for y in range(5) - if x != y - for z in range(5) - if y != z) + return ( + (x, y, z) + for x in range(5) + for y in range(5) + if x != y + for z in range(5) + if y != z + ) ``` --- @@ -543,7 +560,7 @@ #### 2.8.3 ๋‹จ์  -- ๋ฉ”์†Œ๋“œ ์ด๋ฆ„์„ ์ฝ์–ด๋„ ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ์œ ์ถ”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.(e.g. `has_key()`๋Š” ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.) ์ด๊ฑด ์ด์ ์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +- ๋ฉ”์†Œ๋“œ ์ด๋ฆ„์„ ์ฝ์–ด๋„ ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ์œ ์ถ”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.(๋ณ€์ˆ˜์— ํƒ€์ž… ์ฃผ์„์ด ์—†๋Š” ๊ฒฝ์šฐ) ์ด๊ฑด ์ด์ ์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -556,20 +573,16 @@ ```python for key in adict: ... - if key not in adict: ... if obj in alist: ... for line in afile: ... for k, v in adict.items(): ... - for k, v in six.iteritems(adict): ... ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python for key in adict.keys(): ... - if not adict.has_key(key): ... for line in afile.readlines(): ... - for k, v in dict.iteritems(): ... ``` --- @@ -597,13 +610,15 @@ #### 2.9.3 ๋‹จ์  -- ์—†์Šต๋‹ˆ๋‹ค. +- ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๋‚ด์˜ ์ง€์—ญ ๋ณ€์ˆ˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๊ฐ€ ๋ชจ๋‘ ์†Œ๋ชจ๋˜๊ฑฐ๋‚˜ ์ž์ฒด์ ์œผ๋กœ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜๋  ๋•Œ๊นŒ์ง€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. #### 2.9.4 ๊ฒฐ๋ก  - ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜์—์„œ docstring์— ๋Œ€ํ•ด "Returns:"๋ณด๋‹ค "Yields:"๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๊ฐ€ ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ์ž์›์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ, ์ •๋ฆฌ ์ž‘์—…์„ ๊ฐ•์ œ๋กœ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์ •๋ฆฌ ์ž‘์—…์„ ์ž˜ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €๋กœ ๊ฐ์‹ธ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค ([PEP-0533](https://peps.python.org/pep-0533/)). --- @@ -636,9 +651,7 @@ #### 2.10.4 ๊ฒฐ๋ก  -- ๋žŒ๋‹ค๋ฅผ ํ•œ ์ค„๋กœ ์‚ฌ์šฉํ•˜์„ธ์š”. ๋งŒ์•ฝ ์ฝ”๋“œ ๋‚ด๋ถ€์— ์žˆ๋Š” ๋žŒ๋‹ค ํ•จ์ˆ˜๊ฐ€ 60~80๊ธ€์ž ์ˆ˜ ์ •๋„๋กœ ๊ธธ๋‹ค๋ฉด ๊ทธ๊ฑด ์•„๋งˆ ๋” ์ผ๋ฐ˜์ ์ธ - [Lexical Scoping(๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ•‘)](#s2.16-lexical-scoping)์œผ๋กœ ์ •์˜ํ•˜๋Š”๊ฒŒ ๋‚˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. - +- ๋žŒ๋‹ค ํ•จ์ˆ˜๋Š” ํ—ˆ์šฉํ•˜์ง€๋งŒ, ๋žŒ๋‹ค ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์ฝ”๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ์ค„์— ๊ฑธ์น˜๊ฑฐ๋‚˜ 60-80์ž๋ฅผ ๋„˜๋Š” ๊ฒฝ์šฐ, ์ผ๋ฐ˜์ ์ธ [์ค‘์ฒฉ ํ•จ์ˆ˜](#s2.16-lexical-scoping)๋กœ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - ๊ณฑ์…ˆ ๊ฐ™์€ ์ผ๋ฐ˜ ์—ฐ์‚ฐ์ž์—์„œ๋Š” `operator`๋ชจ๋“ˆ ๋Œ€์‹ ์— ๋žŒ๋‹ค ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. - ์˜ˆ๋ฅผ ๋“ค์–ด, `operator.mul`์„ `lambda x,y : x * y` ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. @@ -748,7 +761,7 @@ def foo(a, b=None): if b is None: b = [] - def foo(a, b: Optional[Sequence] = None): + def foo(a, b: Sequence | None = None): if b is None: b = [] def foo(a, b: Sequence = ()): # tuples์€ ๋ถˆ๋ณ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. @@ -758,13 +771,16 @@ - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python + from absl import flags + _FOO = flags.DEFINE_string(...) + def foo(a, b=[]): ... - def foo(a, b=time.time()): # ๋ชจ๋“ˆ์ด ๋กœ๋“œ๊ฐ€ ๋  ๋•Œ์˜ ์‹œ๊ฐ„์ธ๊ฐ€??? + def foo(a, b=time.time()): # `b`๊ฐ€ ์ด ๋ชจ๋“ˆ์ด ๋กœ๋“œ๋œ ์‹œ๊ฐ„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ธ๊ฐ€์š”? ... - def foo(a, b=FLAGS.my_thing): # sys.argv๋Š” ์•„์ง ๊ตฌ๋ฌธ ๋ถ„์„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค... + def foo(a, b=_FOO.value): # sys.argv๋Š” ์•„์ง ๊ตฌ๋ฌธ ๋ถ„์„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค... ... - def foo(a, b: Mapping = {}): # ํ™•์ธ๋˜์ง€ ์•Š์€ ์ฝ”๋“œ๋กœ ์ „๋‹ฌ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค... + def foo(a, b: Mapping = {}): # ํ™•์ธ๋˜์ง€ ์•Š์€ ์ฝ”๋“œ๋กœ ์ „๋‹ฌ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ... ``` @@ -817,7 +833,7 @@ ### 2.14 True/False ํ‰๊ฐ€ -- ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ "์•”๋ฌต์ (implicit)" `false`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ "์•”๋ฌต์ (implicit)" `false`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. (๋ช‡ ๊ฐ€์ง€ ์ฃผ์˜์‚ฌํ•ญ์ด ์žˆ์ง€๋งŒ) @@ -917,7 +933,7 @@ #### 2.16.3 ๋‹จ์  -- ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๋ฒ„๊ทธ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. [PEP-0227](http://www.google.com/url?sa=D&q=http://www.python.org/dev/peps/pep-0227/)์—์„œ ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- [PEP-0227](https://peps.python.org/pep-0227)์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์ด ์˜ˆ์‹œ์™€ ๊ฐ™์ด ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๋ฒ„๊ทธ๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python i = 4 @@ -992,16 +1008,16 @@ - Decorator๋Š” ๋ถ„๋ช…ํ•œ ์ด์ ์ด ์žˆ๋”๋ผ๋„ ํ˜„๋ช…ํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Decorator๋Š” import์™€ ๋ช…๋ช… ์ง€์นจ์„ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค. Decorator pydoc๋Š” decorator ํ•จ์ˆ˜ ์ž„์„ ๋ถ„๋ช…ํžˆ ๋ช…์‹œํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. dcorator๋ฅผ ์œ„ํ•œ ์œ ๋‹› ํ…Œ์ŠคํŠธ(unit test)๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. - Decorator(์˜ˆ. ํŒŒ์ผ, ์†Œ์ผ“, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋“ฑ) ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ (`pydoc` ํ˜น์€ ๊ธฐํƒ€ ๋„๊ตฌ๋ฅผ import ์‹œ๊ฐ„์— ๊ฐ€์ ธ์˜ฌ ๋•Œ) ์‚ฌ์šฉ ๋ชปํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ Decorator์˜ ์™ธ๋ถ€ ์˜์กด์„ฑ์„ ํ”ผํ•˜์„ธ์š”. ์œ ํšจํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง„ Decorator์€ ๋ชจ๋“  ๊ฒฝ์šฐ์— ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณด์žฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- Decorator๋Š” "Top level code"์˜ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์ผ ๋•Œ์—๋Š” [main](#s3.17-main) ํ•ญ๋ชฉ์— ์ž์„ธํ•œ ๋‚ด์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. +- Decorator๋Š” "Top-level code"์˜ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์ผ ๋•Œ์—๋Š” [main](#s3.17-main) ํ•ญ๋ชฉ์— ์ž์„ธํ•œ ๋‚ด์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. - ๊ธฐ์กด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ •์˜๋œ API์™€ ํ†ตํ•ฉํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ•์ œํ•˜์ง€ ์•Š๋Š” ํ•œ "staticmethod"๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. ๋Œ€์‹  ๋ชจ๋“ˆ ๋ ˆ๋ฒจ ํ•จ์ˆ˜๋ฅผ ์“ฐ์„ธ์š”. -- ํ”„๋กœ์„ธ์Šค ์ „์ฒด ์บ์‹œ ๋“ฑ ํ•„์š”ํ•œ global state๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋ช…๋ช…๋œ ์ƒ์„ฑ์ž ๋˜๋Š” ํด๋ž˜์Šค๋ณ„ ๋ฃจํ‹ด์„ ์ž‘์„ฑํ•  ๋•Œ๋งŒ "classmethod"๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- classmethod๋Š” ๋ช…๋ช…๋œ ์ƒ์„ฑ์ž๋ฅผ ์ž‘์„ฑํ•˜๊ฑฐ๋‚˜ ํ”„๋กœ์„ธ์Šค ์ „์ฒด ์บ์‹œ์™€ ๊ฐ™์€ ํ•„์ˆ˜ ์ „์—ญ ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ํด๋ž˜์Šค ํŠน์ • ๋ฃจํ‹ด์„ ์ž‘์„ฑํ•  ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”. --- ### 2.18 ์Šค๋ ˆ๋“œ -- ๋‚ด์žฅ๋œ ํƒ€์ž…์˜ ์›์ž์„ฑ์— ์˜์กดํ•˜์ง€ ๋งˆ์„ธ์š”. ๋”•์…”๋„ˆ๋ฆฌ์™€ ๊ฐ™์€ Python์˜ ๋‚ด์žฅ๋œ ํƒ€์ž…์€ ์›์ž ํ˜•ํƒœ๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ๋Ÿฌ์ง€ ์•Š์€ ๊ฒฝ์šฐ(์˜ˆ: `__hash__`์ด๋‚˜ `__eq__`๊ฐ€ Python ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„๋˜๋Š” ๊ฒฝ์šฐ)๋„ ์žˆ์œผ๋ฉฐ ์›์ž๋กœ ๋˜์–ด์žˆ๋‹ค๊ณ  ์‹ ๋ขฐํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์›์ž ๋ณ€์ˆ˜ ํ• ๋‹น์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. (๊ฒฐ๊ตญ, ๋”•์…”๋„ˆ๋ฆฌ์— ๋‹ฌ๋ ค์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค) ์Šค๋ ˆ๋“œ ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ต์‹ ํ•˜๋Š” ๋ฐ ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํ ๋ชจ๋“ˆ์˜ `Queue` ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด threading ๋ชจ๋“ˆ์ด๋‚˜ locking primitives๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. lower-level lock ๋Œ€์‹ ํ•ด Condition variables์™€ `threading.Condition`๋ฅผ ์„ ํ˜ธํ•˜์„ธ์š”. +- ๋‚ด์žฅ๋œ ํƒ€์ž…์˜ ์›์ž์„ฑ์— ์˜์กดํ•˜์ง€ ๋งˆ์„ธ์š”. ๋”•์…”๋„ˆ๋ฆฌ์™€ ๊ฐ™์€ Python์˜ ๋‚ด์žฅ๋œ ํƒ€์ž…์€ ์›์ž ํ˜•ํƒœ๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ๋Ÿฌ์ง€ ์•Š์€ ๊ฒฝ์šฐ(์˜ˆ: `__hash__`์ด๋‚˜ `__eq__`๊ฐ€ Python ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„๋˜๋Š” ๊ฒฝ์šฐ)๋„ ์žˆ์œผ๋ฉฐ ์›์ž๋กœ ๋˜์–ด์žˆ๋‹ค๊ณ  ์‹ ๋ขฐํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์›์ž ๋ณ€์ˆ˜ ํ• ๋‹น์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. (๊ฒฐ๊ตญ, ๋”•์…”๋„ˆ๋ฆฌ์— ๋‹ฌ๋ ค์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค) ์Šค๋ ˆ๋“œ ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ต์‹ ํ•˜๋Š” ๋ฐ ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ `queue` ๋ชจ๋“ˆ์˜ `Queue` ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด `threading` ๋ชจ๋“ˆ์ด๋‚˜ locking primitives๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. lower-level lock ๋Œ€์‹ ํ•ด Condition variables์™€ `threading.Condition`๋ฅผ ์„ ํ˜ธํ•˜์„ธ์š”. --- @@ -1079,25 +1095,7 @@ from __future__ import generator_stop ``` -- 2.7 ๋ฒ„์ „์„ ๊ณ„์† ์ง€์›ํ•ด์•ผํ•˜๋Š” ๋ถ€๋‹ด์ด ์žˆ๋Š” ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ - - ```python - from __future__ import absolute_import - from __future__ import division - from __future__ import print_function - ``` - - ์ž์„ธํ•œ ๋‚ด์šฉ์€ [Python future statement definitions](https://docs.python.org/3/library/__future__.html) ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. -- ์ฝ”๋“œ๊ฐ€ ์ถฉ๋ถ„ํžˆ ํ˜„๋Œ€์ ์ธ ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉ๋œ๋‹ค๋Š” ํ™•์‹ ์ด ๋“ค ๋•Œ๊นŒ์ง€ ์ด๋Ÿฌํ•œ import๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ๋งˆ์„ธ์š”. -- ํ˜„์žฌ ์ฝ”๋“œ์—์„œ ํŠน์ • ํ–ฅํ›„ import๋ฅผ ํ†ตํ•ด ํ™œ์„ฑํ™”๋˜๋Š” ๊ธฐ๋Šฅ์„ ํ˜„์žฌ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ ํŒŒ์ผ์— ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์œ ์ง€ํ•˜๋ฉด ๋‚˜์ค‘์— ์ฝ”๋“œ๊ฐ€ ์ด์ „ ๋™์ž‘์— ๋”ฐ๋ผ ์‹ค์ˆ˜๋กœ ์ˆ˜์ •๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -- ์ ์ ˆํ•˜๋‹ค๊ณ  ์ƒ๊ฐ๋˜๋Š” ๋‹ค๋ฅธ `from __future__` import ๋ฌธ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. -- 2.7๋ฒ„์ „ ๋‚ด์— ์—ฌ๋Ÿฌ ์œ„์น˜์—์„œ ๋„์ž…๋œ ์•”์‹œ์  ๊ธฐ๋ณธ ์ฝ”๋ฑ ๋ณ€ํ™˜ ๊ฒฐ๊ณผ๋กœ ์ธํ•ด ํ™•์‹คํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— 2.7๋ฒ„์ „์— ๋Œ€ํ•œ ๊ถŒ์žฅ ์‚ฌํ•ญ์— `unicode_literals`๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. -- ๋Œ€๋ถ€๋ถ„์˜ ์ด์ค‘ ๋ฒ„์ „ 2-3 ์ฝ”๋“œ๋Š” ํ•„์š”ํ•œ ๊ฒฝ์šฐ `b''` ์™€ `u''` q๋ฐ”ํŠธ์™€ ์œ ๋‹ˆ์ฝ”๋“œ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์„ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์•˜์Šต๋‹ˆ๋‹ค. - -##### six, future ๊ทธ๋ฆฌ๊ณ  past ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ - -- ํ”„๋กœ์ ํŠธ๊ฐ€ ์—ฌ์ „ํžˆ Python 2, 3 ๋ชจ๋‘์—์„œ ์‚ฌ์šฉ์„ ์ง€์›ํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ ์ ํ•ฉํ•˜๋‹ค๊ณ  ํŒ๋‹จ๋˜๋Š” ๋Œ€๋กœ [six](https://pypi.org/project/six/), [future](https://pypi.org/project/future/), ๋ฐ [past](https://pypi.org/project/past/) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ์ฝ”๋“œ๋ฅผ ๋” ๊นจ๋—ํ•˜๊ณ  ์‚ถ์„ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. --- @@ -1105,8 +1103,8 @@ ### 2.21 Type ์ฃผ์„ -- Python 3์—์„œ ํƒ€์ž…์˜ ์ •๋ณด๋ฅผ [PEP-484](https://www.python.org/dev/peps/pep-0484/)์˜ ์ฐธ๊ณ ํ•ด์„œ ์ฃผ์„์œผ๋กœ ๋‹ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋นŒ๋“œ ํ•  ๋•Œ [pytype](https://github.com/google/pytype)๊ฐ™์€ ํƒ€์ž…๊ฒ€์‚ฌ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- Type์— ๋Œ€ํ•œ ์ฃผ์„์€ ์†Œ์Šค ์•ˆ์ด๋‚˜ [stub pyi ํŒŒ์ผ](https://www.python.org/dev/peps/pep-0484/#stub-files)์— ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•˜๋ฉด ์ฃผ์„์€ ์†Œ์Šค์•ˆ์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์‚ฌ ๋˜๋Š” ํ™•์žฅ ๋ชจ๋“ˆ์—๋Š” pyi ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- Python์—์„œ ํƒ€์ž…์˜ ์ •๋ณด๋ฅผ [PEP-484](https://www.python.org/dev/peps/pep-0484/)์˜ ์ฐธ๊ณ ํ•ด์„œ ์ฃผ์„์œผ๋กœ ๋‹ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋นŒ๋“œ ํ•  ๋•Œ [pytype](https://github.com/google/pytype)๊ฐ™์€ ํƒ€์ž…๊ฒ€์‚ฌ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- Type์— ๋Œ€ํ•œ ์ฃผ์„์€ ์†Œ์Šค ์•ˆ์ด๋‚˜ [stub pyi ํŒŒ์ผ](https://peps.python.org/pep-0484/#stub-files)์— ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•˜๋ฉด ์ฃผ์„์€ ์†Œ์Šค์•ˆ์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์‚ฌ ๋˜๋Š” ํ™•์žฅ ๋ชจ๋“ˆ์—๋Š” pyi ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -1115,21 +1113,15 @@ - Type์˜ ์ฃผ์„(ํ˜น์€ Type ์ •๋ณด)์€ ํ•จ์ˆ˜๋‚˜ ๋ฉ”์„œ๋“œ์˜ ์ธ์ž๊ฐ’์ด๋‚˜ ๋ฐ˜ํ™˜๊ฐ’์ž…๋‹ˆ๋‹ค ```python - def func(a: int) -> List[int]: + def func(a: int) -> list[int]: ``` -- [PEP-526](https://www.python.org/dev/peps/pep-0526/)๊ตฌ๋ฌธ ์ฒ˜๋Ÿผ ๋ณ€์ˆ˜์˜ type์„ ์„ ์–ธํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +- [PEP-526](https://peps.python.org/pep-0526/)๊ตฌ๋ฌธ ์ฒ˜๋Ÿผ ๋ณ€์ˆ˜์˜ type์„ ์„ ์–ธํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ```python a: SomeType = some_func() ``` -- legacy Python version์„ ์ง€์›ํ•ด์•ผํ•œ๋‹ค๋ฉด ์ฝ”๋“œ์— type ์„ค๋ช…์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. - - ```python - a = some_func() # type: SomeType - ``` - #### 2.21.2 ์žฅ์  @@ -1175,10 +1167,10 @@ - ๊ฒฝ๋กœ์ด๋ฆ„์ด๋‚˜ URLs์™€ ๊ฐ™์€ ๊ณต๋ฐฑ์„ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ๊ธด ๋ชจ๋“ˆ์ˆ˜์ค€ ๋ฌธ์ž์ƒ์ˆ˜๋Š” ์—ฌ๋Ÿฌ ์ค„์— ๋‚˜๋ˆ„์–ด ๊ธฐ๋กํ•˜๊ธฐ ๋ถˆํŽธํ•  ๊ฒฝ์šฐ - Pylint ๋น„ํ™œ์„ฑํ™” ์ฃผ์„๋ฌธ (e.g.: `# pylint: disable=invalid-name`) -- 3๊ฐœ ์ด์ƒ์˜ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €๋ฅผ ์š”๊ตฌํ•˜๋Š” `with` ๊ตฌ๋ฌธ์„ ์ œ์™ธํ•˜๊ณ  ๋ฐฑ์Šฌ๋ž˜์‰ฌ(`\`) ๋ฅผ ์ด์šฉํ•œ ๋ฌธ์žฅ์—ฐ์žฅ์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. - -- Python์˜ [์†Œ/์ค‘/๋Œ€ ๊ด„ํ˜ธ ๋‚ด๋ถ€์˜ ๋ฌต์‹œ์  ๋ผ์ธ๊ฒฐํ•ฉ](http://docs.python.org/reference/lexical_analysis.html#implicit-line-joining)์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- [๋ช…์‹œ์ ์ธ ์ค„ ์—ฐ์†](https://docs.python.org/3/reference/lexical_analysis.html#explicit-line-joining)์„ ์œ„ํ•ด ๋ฐฑ์Šฌ๋ž˜์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. +- ๋Œ€์‹ ์— Python์˜ [์†Œ/์ค‘/๋Œ€ ๊ด„ํ˜ธ ๋‚ด๋ถ€์˜ ๋ฌต์‹œ์  ๋ผ์ธ๊ฒฐํ•ฉ](http://docs.python.org/reference/lexical_analysis.html#implicit-line-joining)์„ ์‚ฌ์šฉํ•˜์„ธ์š”. - ํ•„์š”ํ•˜๋‹ค๋ฉด, ๊ตฌ๋ฌธ ์–‘์ชฝ์— ์ถ”๊ฐ€๋กœ ๊ด„ํ˜ธ๋ฅผ ๋”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- ์ด ๊ทœ์น™์€ ๋ฌธ์ž์—ด ๋‚ด์—์„œ ๋ฐฑ์Šฌ๋ž˜์‹œ๋กœ ์ด์Šค์ผ€์ดํ”„๋œ ๊ฐœํ–‰์„ ๊ธˆ์ง€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์•„๋ž˜ [์ฐธ์กฐ](#strings)). - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -1186,8 +1178,29 @@ foo_bar(self, width, height, color='black', design=None, x='foo', emphasis=None, highlight=0) - if (width == 0 and height == 0 and - color == 'red' and emphasis == 'strong'): + if (width == 0 and height == 0 and + color == 'red' and emphasis == 'strong'): + (bridge_questions.clarification_on + .average_airspeed_of.unladen_swallow) = 'African or European?' + with ( + very_long_first_expression_function() as spam, + very_long_second_expression_function() as beans, + third_thing() as eggs, + ): + place_order(eggs, beans, spam, beans) + ``` + + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ + + ```python + if width == 0 and height == 0 and \ + color == 'red' and emphasis == 'strong': + bridge_questions.clarification_on \ + .average_airspeed_of.unladen_swallow = 'African or European?' + with very_long_first_expression_function() as spam, \ + very_long_second_expression_function() as beans, \ + third_thing() as eggs: + place_order(eggs, beans, spam, beans) ``` - ๋งŒ์•ฝ ๋ฆฌํ„ฐ๋Ÿด ๋ฌธ์ž์—ด์„ ํ•œ ์ค„์— ํ‘œํ˜„ํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ด„ํ˜ธ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฌต์‹œ์  ๋ผ์ธ๊ฒฐํ•ฉ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -1197,56 +1210,55 @@ 'long long long long long long string') ``` -- ์ฃผ์„์˜ ๊ฒฝ์šฐ ๊ธด URLs ๋“ค์€ ํ•œ์ค„์— ํ‘œํ˜„ํ•˜์„ธ์š”. +- ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ๋†’์€ ๊ตฌ๋ฌธ ์ˆ˜์ค€์—์„œ ์ค„์„ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜์„ธ์š”. ์ค„์„ ๋‘ ๋ฒˆ ๋‚˜๋ˆ ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ, ๋‘ ๋ฒˆ ๋ชจ๋‘ ๋™์ผํ•œ ๊ตฌ๋ฌธ ์ˆ˜์ค€์—์„œ ๋‚˜๋ˆ„์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - # See details at - # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html + bridgekeeper.answer( + name="Arthur", quest=questlib.find(owner="Arthur", perilous=True)) + answer = (a_long_line().of_chained_methods() + .that_eventually_provides().an_answer()) + if ( + config is None + or 'editor.language' not in config + or config['editor.language'].use_spaces is False + ): + use_tabs() ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - # See details at - # http://www.example.com/us/developer/documentation/api/content/\ - # v2.0/csv_file_name_extension_full_specification.html + bridgekeeper.answer(name="Arthur", quest=questlib.find( + owner="Arthur", perilous=True)) + answer = a_long_line().of_chained_methods().that_eventually_provides( + ).an_answer() + if (config is None or 'editor.language' not in config or config[ + 'editor.language'].use_spaces is False): + use_tabs() ``` -- 3์ค„ ์ด์ƒ์ด ํ•„์š”ํ•œ `with` ๊ตฌ๋ฌธ์„ ์ •์˜ํ•  ๋•Œ๋Š” ๋ฐฑ์Šฌ๋ž˜์‰ฌ(`\`) ๋ฅผ ์ด์šฉํ•œ ๋ฌธ์žฅ์—ฐ์žฅ์ด ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. 2์ค„์ธ ๊ฒฝ์šฐ ๋„ค์Šคํ‹ฐ๋“œ `with`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š” +- ์ฃผ์„์˜ ๊ฒฝ์šฐ ๊ธด URLs ๋“ค์€ ํ•œ์ค„์— ํ‘œํ˜„ํ•˜์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - with very_long_first_expression_function() as spam, \ - very_long_second_expression_function() as beans, \ - third_thing() as eggs: - place_order(eggs, beans, spam, beans) + # See details at + # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - with VeryLongFirstExpressionFunction() as spam, \ - VeryLongSecondExpressionFunction() as beans: - PlaceOrder(beans, spam) - ``` - - - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ - - ```python - with very_long_first_expression_function() as spam: - with very_long_second_expression_function() as beans: - place_order(beans, spam) + # See details at + # http://www.example.com/us/developer/documentation/api/content/\ + # v2.0/csv_file_name_extension_full_specification.html ``` - ์œ„์˜ ์˜ˆ์‹œ์—์„œ ๊ฐ ์š”์†Œ์— ์‚ฌ์šฉ๋œ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์ž˜ ๊ธฐ์–ตํ•˜์„ธ์š”. ๋” ์ž์„ธํ•œ ์ •๋ณด๋Š” [๋“ค์—ฌ์“ฐ๊ธฐ](#s3.4-indentation) ์ฑ•ํ„ฐ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. +- ์œ„์—์„œ ์–ธ๊ธ‰๋˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ ํ•œ ์ค„์˜ ๊ธธ์ด๊ฐ€ 80์ž๋ฅผ ์ดˆ๊ณผํ•จ์—๋„ [Black](https://github.com/psf/black) ํ˜น์€ [Pyink](https://github.com/google/pyink) ์˜คํ† ํฌ๋ฉ”ํ„ฐ๊ฐ€ ๋ณ„๋‹ค๋ฅธ ๋„์›€์„ ์ฃผ์ง€ ๋ชปํ•œ๋‹ค๋ฉด 80์ž ์ด์ƒ ์ดˆ๊ณผ๊ฐ€ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ž‘์„ฑ์ž๋Š” ์ƒ์‹์ ์ธ ์ˆ˜์ค€๋‚ด์—์„œ ์œ„ ๋ฌธ์„œ์˜ ์‚ฌํ•ญ์„ ์ฐธ๊ณ ํ•˜์—ฌ ์ค„์„ ๋ถ„๋ฆฌํ•˜๋Š”๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•ฉ๋‹ˆ๋‹ค. -์œ„์—์„œ ์–ธ๊ธ‰๋˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ ํ•œ ์ค„์˜ ๊ธธ์ด๊ฐ€ 80์ž๋ฅผ ์ดˆ๊ณผํ•จ์—๋„ -[yapf](https://github.com/google/yapf/) -์˜คํ† ํฌ๋ฉ”ํ„ฐ๊ฐ€ ๋ณ„๋‹ค๋ฅธ ๋„์›€์„ ์ฃผ์ง€ ๋ชปํ•œ๋‹ค๋ฉด 80์ž ์ด์ƒ ์ดˆ๊ณผ๊ฐ€ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. -์ž‘์„ฑ์ž๋Š” ์ƒ์‹์ ์ธ ์ˆ˜์ค€๋‚ด์—์„œ ์œ„ ๋ฌธ์„œ์˜ ์‚ฌํ•ญ์„ ์ฐธ๊ณ ํ•˜์—ฌ ์ค„์„ ๋ถ„๋ฆฌํ•˜๋Š”๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•ฉ๋‹ˆ๋‹ค. --- @@ -1293,26 +1305,26 @@ - ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ _4 ์นธ_ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ํ•˜์„ธ์š”. -- ํƒญ์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํƒญ๊ณผ ์ŠคํŽ˜์ด์Šค๋ฅผ ์„ž์–ด์„œ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. -- ๋ฌต์‹œ์  ๋ฌธ์žฅ์—ฐ์žฅ์˜ ๊ฒฝ์šฐ [line length](#s3.2-line-length) ์„น์…˜์˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ๋™์ผํ•œ ๋ฌธ์žฅ์— ํฌํ•จ๋œ ์š”์†Œ๋“ค์„ ์ˆ˜์ง์ •๋ ฌํ•˜๊ฑฐ๋‚˜ ์ฒซ ์—ด๋ฆฐ๊ด„ํ˜ธ ์ดํ›„๋กœ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†๋Š” 4 ์นธ hanging indent ๋ฅผ ์ ์šฉํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ํƒญ์„ ์ ˆ๋Œ€ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. ์•”์‹œ๋œ ์ค„ ์—ฐ์†์€ ๋ž˜ํ•‘๋œ ์š”์†Œ๋ฅผ ์ˆ˜์ง์œผ๋กœ ์ •๋ ฌํ•ด์•ผ ํ•˜๋ฉฐ([์ค„ ๊ธธ์ด ์˜ˆ์ œ](#s3.2-line-length) ์ฐธ์กฐ), ๋˜๋Š” 4๊ฐœ์˜ ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ–‰์„ ๋“ค์—ฌ์“ฐ๊ธฐ ํ•˜์„ธ์š”. +- ๋‹ซ๋Š” ๊ด„ํ˜ธ(์›, ๋Œ€๊ฐ์„  ๋˜๋Š” ์ค‘๊ด„ํ˜ธ)๋Š” ํ‘œํ˜„์‹์˜ ๋์— ๋ฐฐ์น˜ํ•˜๊ฑฐ๋‚˜ ๋ณ„๋„์˜ ์ค„์— ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด ๊ฒฝ์šฐ ํ•ด๋‹น ์—ฌ๋Š” ๊ด„ํ˜ธ์™€ ๊ฐ™์€ ์ค„์— ๋“ค์—ฌ์“ฐ๊ธฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - # Aligned with opening delimiter + # ์—ฌ๋Š” ๊ตฌ๋ถ„ ๊ธฐํ˜ธ์™€ ์ •๋ ฌ๋จ foo = long_function_name(var_one, var_two, var_three, var_four) meal = (spam, beans) - # Aligned with opening delimiter in a dictionary + # ๋”•์…”๋„ˆ๋ฆฌ์˜ ์—ฌ๋Š” ๊ตฌ๋ถ„ ๊ธฐํ˜ธ์™€ ์ •๋ ฌ๋จ foo = { 'long_dictionary_key': value1 + value2, ... } - # 4-space hanging indent; nothing on first line + # 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ, ์ฒซ ๋ฒˆ์งธ ์ค„์—๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†์Œ foo = long_function_name( var_one, var_two, var_three, var_four) @@ -1320,7 +1332,16 @@ spam, beans) - # 4-space hanging indent in a dictionary + # 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ; ์ฒซ ๋ฒˆ์งธ ์ค„์—๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†์Œ, ๋‹ซ๋Š” ๊ด„ํ˜ธ๋Š” ์ƒˆ ์ค„์— ๋ฐฐ์น˜ + foo = long_function_name( + var_one, var_two, var_three, + var_four + ) + meal = ( + spam, + beans, + ) + # ๋”•์…”๋„ˆ๋ฆฌ์—์„œ 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ foo = { 'long_dictionary_key': long_dictionary_value, @@ -1331,18 +1352,18 @@ - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - # Stuff on first line forbidden + # ์ฒซ ๋ฒˆ์งธ ์ค„์— ๋‚ด์šฉ์ด ์žˆ์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. foo = long_function_name(var_one, var_two, var_three, var_four) meal = (spam, beans) - # 2-space hanging indent forbidden + # 2์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ๋Š” ๊ธˆ์ง€๋ฉ๋‹ˆ๋‹ค. foo = long_function_name( var_one, var_two, var_three, var_four) - # No hanging indent in a dictionary + # ๋”•์…”๋„ˆ๋ฆฌ์—์„œ๋Š” ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. foo = { 'long_dictionary_key': long_dictionary_value, @@ -1354,8 +1375,8 @@ #### 3.4.1 ์›์†Œ ๋‚˜์—ด ์‹œ ํ›„ํ–‰ ์‰ผํ‘œ -- ์—ฌ๋Ÿฌ ์›์†Œ๋ฅผ ๋‚˜์—ดํ•  ๋•Œ ํ›„ํ–‰ ์‰ผํ‘œ๋Š” `]`, `)`, `}` ์™€ ๊ฐ™์ด ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋‹ซ๋Š” ํ† ํฐ์ด ๋งˆ์ง€๋ง‰ ์›์†Œ์™€ ๊ฐ™์€ ์ค„์— ์žˆ์ง€ ์•Š์„ ๋•Œ๋งŒ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. -- ๋˜ํ•œ ํ›„ํ–‰ ์‰ผํ‘œ์˜ ์กด์žฌ ์—ฌ๋ถ€๋Š” ํŒŒ์ด์ฌ ์ฝ”๋“œ ์˜คํ† -ํฌ๋ฉ”ํ„ฐ [YAPF](https://pypi.org/project/yapf/) ๊ฐ€ ์ปจํ…Œ์ด๋„ˆ์˜ ์›์†Œ๋ฅผ ํ•œ ์ค„์— ํ•˜๋‚˜์”ฉ `,` ๊ธฐํ˜ธ๋ฅผ ๋ถ™์—ฌ ์ž๋™ ์ •๋ ฌํ•˜๋„๋ก ์ง€์‹œํ•˜๋Š” ํžŒํŠธ๋กœ๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. +- ํ›„ํ–‰ ์‰ผํ‘œ๋Š” ์‹œํ€€์Šค์˜ ์š”์†Œ์—์„œ ๋‹ซ๋Š” ๊ตฌ๋ฌธ ๊ธฐํ˜ธ `]`, `)`, ๋˜๋Š” `}`๊ฐ€ ๋งˆ์ง€๋ง‰ ์š”์†Œ์™€ ๊ฐ™์€ ์ค„์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์™€ ๋‹จ์ผ ์š”์†Œ๋ฅผ ๊ฐ€์ง„ ํŠœํ”Œ์— ๋Œ€ํ•ด์„œ๋งŒ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. +- ํ›„ํ–‰ ์‰ผํ‘œ์˜ ์กด์žฌ๋Š” Python ์ฝ”๋“œ ์ž๋™ ํฌ๋งทํ„ฐ์ธ [Black](https://github.com/psf/black)์ด๋‚˜ [Pyink](https://github.com/google/pyink)์—๊ฒŒ ๋งˆ์ง€๋ง‰ ์š”์†Œ ๋’ค์— `,`๊ฐ€ ์žˆ์„ ๋•Œ ํ•ญ๋ชฉ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ•œ ์ค„์— ํ•˜๋‚˜์˜ ํ•ญ๋ชฉ์”ฉ ์ž๋™์œผ๋กœ ํฌ๋งทํ•˜๋„๋ก ์ง€์‹œํ•˜๋Š” ํžŒํŠธ๋กœ๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -1376,8 +1397,7 @@ 0, 1, 4, - 6 - ] + 6,] ``` --- @@ -1386,7 +1406,7 @@ ### 3.5 Blank Lines - ํ•จ์ˆ˜ ์„ ์–ธ์ด๋“  ๊ฐ์ฒด ์„ ์–ธ์ด๋“  ์ตœ์ƒ์œ„ ์„ ์–ธ๋ฌธ๊ณผ๋Š” 2๊ฐœ์˜ ๋นˆ ์ค„์„ ์‚ฌ์ด์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๊ฐ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ๋˜๋Š” `class` ์ค„๊ณผ ์ “ ๋ฒˆ์งธ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ์‹œ ๊ทธ ์‚ฌ์ด์—๋Š” ํ•œ ๊ฐœ์˜ ๋นˆ ์ค„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๊ฐ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ๋˜๋Š” `class`์˜ docstring ์ค„๊ณผ ์ “ ๋ฒˆ์งธ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ์‹œ ๊ทธ ์‚ฌ์ด์—๋Š” ํ•œ ๊ฐœ์˜ ๋นˆ ์ค„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - `def` ์ค„ ์ดํ›„์—๋Š” ๋นˆ ์ค„์ด ์—†์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ํ•จ์ˆ˜์™€ ๋ฉ”์†Œ๋“œ ์‚ฌ์ด์— ๊ฐœ๋ฐœ์ž์˜ ํŒ๋‹จํ•˜์— ์ ์ ˆํ•˜๊ฒŒ ํ•œ ๊ฐœ์˜ ๋นˆ ์ค„์„ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -1524,7 +1544,7 @@ ### 3.7 Shebang Line - ๋Œ€๋ถ€๋ถ„์˜ `.py` ํŒŒ์ผ์€ `#!` ๋กœ ์‹œ์ž‘ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. -- [PEP-394](https://www.python.org/dev/peps/pep-0394/)์— ๋”ฐ๋ผ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ฉ”์ธ ํŒŒ์ผ ์ฒซ ์ค„์— `#!/usr/bin/env python3` (virtualenvs ์ง€์›) ๋˜๋Š” `#!/usr/bin/python3`์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. +- [PEP-394](https://peps.python.org/pep-0394/)์— ๋”ฐ๋ผ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ฉ”์ธ ํŒŒ์ผ ์ฒซ ์ค„์— `#!/usr/bin/env python3` (virtualenvs ์ง€์›) ๋˜๋Š” `#!/usr/bin/python3`์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. - ์ด ์ค„์€ ํŒŒ์ด์ฌ ํŒŒ์ผ์„ import ํ• ๋•Œ๋Š” ๋ฌด์‹œ๋˜์ง€๋งŒ ์‹คํ–‰ ๋ ๋•Œ๋Š” ์ปค๋„์ด ์–ด๋–ค ํŒŒ์ด์ฌ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. - ๋”ฐ๋ผ์„œ ์ง์ ‘ ์‹คํ–‰๋  ํŒŒ์ผ์— ๊ธฐ๋กํ•˜๋Š”๊ฒƒ์ด ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. @@ -1543,7 +1563,7 @@ - ํŒŒ์ด์ฌ์€ ์ฝ”๋“œ๋ฅผ ๋ฌธ์„œํ™” ํ•  ๋•Œ _docstring_ ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. - docstring ์€ ํŒจํ‚ค์ง€, ๋ชจ๋“ˆ, ํด๋ž˜์Šค๋‚˜ ํ•จ์ˆ˜์˜ ์ฒซ๋ฒˆ์งธ ์„ ์–ธ๋˜๋Š” ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. - ์ด ๋ฌธ์ž์—ด์€ `pydoc` ์ด ์‚ฌ์šฉํ•˜๋Š” `__doc__` ๋ฉค๋ฒ„ ์˜ค๋ธŒ์ ํŠธ์—์„œ ์ž๋™์œผ๋กœ ์ถ”์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์—ฌ๋Ÿฌ๋ถ„์˜ ๋ชจ๋“ˆ์—์„œ `pydoc` ๋ฅผ ์‹คํ–‰ ํ›„ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ณด์„ธ์š”) -- [PEP257](https://www.google.com/url?sa=D&q=http://www.python.org/dev/peps/pep-0257/) ์— ๋”ฐ๋ผ docstring ์„ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋๋‚ผ ๋•Œ๋Š” `"""` ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- [PEP257](https://peps.python.org/pep-0257/) ์— ๋”ฐ๋ผ docstring ์„ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋๋‚ผ ๋•Œ๋Š” `"""` ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. - docstring์€ ๋งˆ์นจํ‘œ, ๋ฌผ์Œํ‘œ, ๋Š๋‚Œํ‘œ๋กœ ๋๋‚˜๋Š” ์š”์•ฝ์ค„(ํ•œ ์ค„)๋กœ ์‹œ์ž‘ํ•˜์—ฌ์•ผ ํ•˜๋ฉฐ ํ•œ ์ค„์˜ ๊ณต๋ฐฑ์„ ๋‘๊ณ  ๋‚ด์šฉ์„ ๋‹ด๊ณ ์žˆ๋Š” ๋‚˜๋จธ์ง€ docstring ์ด ์ด์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ๋˜ํ•œ ๋‚ด์šฉ์„ ๋‹ด๊ณ ์žˆ๋Š” docstring ์€ `"""` ์™€ ๊ฐ™์€ ์ปค์„œ์œ„์น˜์—์„œ ์‹œ์ž‘ํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -1551,36 +1571,70 @@ #### 3.8.2 Modules -- ๋ชจ๋“  ํŒŒ์ผ์€ ๋ผ์ด์„ผ์Šค ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ํ”„๋กœ์ ํŠธ์— ์•Œ๋งž๋Š” ๋ผ์ด์„ผ์Šค ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ์„ ํƒํ•˜์„ธ์š”. (์˜ˆ๋ฅผ ๋“ค๋ฉด, Apache 2.0, BSD, LGPL, GPL) +- ๋ชจ๋“  ํŒŒ์ผ์€ ๋ผ์ด์„ผ์Šค ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + + ```python + """๋ชจ๋“ˆ์ด๋‚˜ ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•œ ํ•œ ์ค„ ์š”์•ฝ์œผ๋กœ, ๋งˆ์นจํ‘œ๋กœ ๋๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. + + ํ•œ ์ค„์„ ๋น„์›Œ๋‘์„ธ์š”. ์ด docstring์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์—๋Š” ๋ชจ๋“ˆ์ด๋‚˜ ํ”„๋กœ๊ทธ๋žจ์— + ๋Œ€ํ•œ ์ „๋ฐ˜์ ์ธ ์„ค๋ช…์ด ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์„ ํƒ์ ์œผ๋กœ, ๋‚ด๋ณด๋‚ธ ํด๋ž˜์Šค์™€ + ํ•จ์ˆ˜์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ์„ค๋ช… ๋ฐ/๋˜๋Š” ์‚ฌ์šฉ ์˜ˆ์‹œ๋„ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + ์ „ํ˜•์ ์ธ ์‚ฌ์šฉ ์˜ˆ์‹œ: + + foo = ClassFoo() + bar = foo.FunctionBar() + """ + ``` + + + + +##### 3.8.2.1 Test modules + +- ํ…Œ์ŠคํŠธ ํŒŒ์ผ์˜ ๋ชจ๋“ˆ ์ˆ˜์ค€ docstring์€ ํ•„์ˆ˜๋Š” ์•„๋‹™๋‹ˆ๋‹ค. +- ์ถ”๊ฐ€์ ์ธ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•  ํ•„์š”๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์˜ˆ๋ฅผ ๋“ค๋ฉด, ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ๋‚ด์šฉ, ํŠน์ดํ•œ ์„ค์ • ํŒจํ„ด์— ๋Œ€ํ•œ ์„ค๋ช…, ์™ธ๋ถ€ ํ™˜๊ฒฝ์— ๋Œ€ํ•œ ์˜์กด์„ฑ ๋“ฑ์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +"""์ด Blaze ํ…Œ์ŠคํŠธ๋Š” golden ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +`google3` ๋””๋ ‰ํ† ๋ฆฌ์—์„œ +`blaze run //foo/bar:foo_test -- --update_golden_files` ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜์—ฌ +์ด๋Ÿฌํ•œ ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +""" +``` + +- ์ƒˆ๋กœ์šด ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” docstring์€ ์‚ฌ์šฉํ•˜์ง€ ๋ง์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +```python +"""Tests for foo.bar.""" +``` #### 3.8.3 Functions and Methods -- ์ด ์„น์…˜์—์„œ "ํ•จ์ˆ˜"๋Š” ๋ฉ”์†Œ๋“œ, ํ•จ์ˆ˜ ๋˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. +- ์ด ์„น์…˜์—์„œ โ€˜functionโ€™์€ ๋ฉ”์†Œ๋“œ, ํ•จ์ˆ˜, ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๋˜๋Š” ์†์„ฑ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. -- ์•„๋ž˜์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ํ•จ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ docstring ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜ ์ด์ƒ์˜ ์†์„ฑ์„ ๊ฐ€์ง„ ๋ชจ๋“  ํ•จ์ˆ˜์—๋Š” docstring์ด ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค. - - ์™ธ๋ถ€์—์„œ ๋ณด์ด์ง€ ์•Š์Œ - - ๋งค์šฐ ์งง์Œ - - ์ž˜ ์•Œ๋ ค์ ธ ์žˆ์Œ + - ๊ณต๊ฐœ API์˜ ์ผ๋ถ€์ธ ๊ฒฝ์šฐ + - ๋น„๊ต์  ํฐ ๊ฒฝ์šฐ + - ์ง๊ด€์ ์ด์ง€ ์•Š์€ ๋กœ์ง์„ ๊ฐ€์ง„ ๊ฒฝ์šฐ -- docstring ์€ ์ง์ ‘ ํ•จ์ˆ˜์˜ ์ฝ”๋“œ๋ฅผ ์ฝ์–ด๋ณด์ง€ ์•Š๋”๋ผ๋„ ์ถฉ๋ถ„ํžˆ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ ํ•  ์ˆ˜ ์žˆ์„๋งŒํผ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- docstring์€ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ๋ฐฉ์‹์ด๋‚˜ ์‹œ๋ฉ˜ํ‹ฑ๋“ฑ์„ ๋ฐ˜๋“œ์‹œ ๊ธฐ์ˆ ํ•˜๋˜ ํ•จ์ˆ˜์˜ ์‚ฌ์šฉํ•จ์— ์žˆ์–ด ์˜ํ•ญ์„ ์ฃผ์ง€ ์•Š๋Š” ํ•œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์ƒ์„ธํ•œ ๊ตฌํ˜„๋ฐฉ๋ฒ•์€ ๊ธฐ์ˆ ํ•˜์ง€ ์•„๋‹ˆํ•ฉ๋‹ˆ๋‹ค -- ์˜ˆ๋ฅผ๋“ค์–ด ํ•œ ํ•จ์ˆ˜๊ฐ€ ๊ตฌ๋™๊ณผ์ •์—์„œ ์ธ์ž๋กœ ๋ฐ›์€ ๋ณ€์ˆ˜ ํ•˜๋‚˜๋ฅผ ๋ณ€ํ˜•์‹œํ‚จ๋‹ค๋ฉด ์ด๋Š” docstring์— ๊ธฐ์ˆ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์ด์™ธ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ๊ณผ ์ƒ๊ด€์ด ์—†๋Š” ์ž์ž˜ํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ ํ•ญ๋ชฉ๋“ค์€ ํ•จ์ˆ˜ ๋‚ด docstring ๋ณด๋‹จ ์ฃผ์„์œผ๋กœ ๊ธฐ๋กํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค -- docstring ์€ (`"""Fetches rows from a Bigtable."""`) ์ฒ˜๋Ÿผ _์„ค๋ช…์กฐ_ ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ์•ผ ํ•˜๋ฉฐ (`"""Fetch rows from a Bigtable."""`) ์ฒ˜๋Ÿผ _๋ช…๋ น์กฐ_ ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- docstring ์€ ํ•จ์ˆ˜์˜ ๊ตฌํ˜„๋ฐฉ์‹์ด ์•„๋‹Œ ํ˜ธ์ถœ ๋ฐฉ๋ฒ•๊ณผ ์˜๋ฏธ๋ฅผ ๊ธฐ์ˆ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋ณต์žกํ•œ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ docstring ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์ฝ”๋“œ ํ•œ ์ค„๋งˆ๋‹ค ์ฃผ์„์„ ์ฒจ๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ๋” ์•Œ๋งž์Šต๋‹ˆ๋‹ค. +- docstring์€ ํ•จ์ˆ˜์˜ ์ฝ”๋“œ๋ฅผ ์ฝ์ง€ ์•Š๊ณ ๋„ ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์„ ๋งŒํผ ์ถฉ๋ถ„ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- docstring์€ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ ๊ตฌ๋ฌธ๊ณผ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•ด์•ผ ํ•˜๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ ํฌํ•จํ•˜์ง€ ์•Š์•„์•ผ ํ•˜์ง€๋งŒ, ์ด๋Ÿฌํ•œ ์„ธ๋ถ€ ์‚ฌํ•ญ์ด ํ•จ์ˆ˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ์ค‘์š”ํ•˜๋‹ค๋ฉด ์˜ˆ์™ธ์ž…๋‹ˆ๋‹ค. +- ์˜ˆ๋ฅผ ๋“ค์–ด, ์ธ์ž๋ฅผ ์‚ฌ์ด๋“œ ์ž„ํŽ™ํŠธ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜๋Š” ๊ทธ ์ ์„ docstring์— ๋ช…์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋‹ค๋ฅธ ๊ธฐ๋ณธ ๊ฐ์ฒด์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋Š” `"""See base class."""` ์ฒ˜๋Ÿผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ docstring ์— ์˜ค๋ฒ„๋ผ์ด๋“œ๋œ ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ์Œ์„ ์•Œ๋ ค์ฃผ๋Š” docstring ์„ ์ „๋‹ฌ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -- ๊ทธ ์ด์œ ๋Š” ๊ฐ™์€ ๋ฌธ์„œ๋ฅผ ์—ฌ๋Ÿฌ๊ณณ์—์„œ ๋ฐ˜๋ณตํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. -- ํ•˜์ง€๋งŒ ์˜ค๋ฒ„๋ผ์ด๋”ฉ๋œ ๋ฉ”์†Œ๋“œ๊ฐ€ ๊ธฐ์กด์˜ ๋ฉ”์†Œ๋“œ์™€ ํ™•์—ฐํ•˜๊ฒŒ ๋‹ค๋ฅธ ๋™์ž‘๋ฐฉ์‹์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ฑฐ๋‚˜ ์„ธ๋ถ€์ ์ธ ๋‚ด์šฉ(e.g., ์ž ์žฌ์ ์ธ ๋ถ€์ž‘์šฉ ๋“ฑ)์ด ์กด์žฌํ•œ๋‹ค๋ฉด ์ ์–ด๋„ ๊ทธ๋Ÿฌํ•œ ์ฐจ์ด์ ๋“ค์€ docstring ์„ ํ†ตํ•ด ๊ธฐ๋ก๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, ํ˜ธ์ถœ์ž์—๊ฒŒ ์ค‘์š”ํ•˜์ง€ ์•Š์€ ํ•จ์ˆ˜ ๊ตฌํ˜„์˜ ๋ฏธ๋ฌ˜ํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ ํ•จ์ˆ˜์˜ docstring๋ณด๋‹ค๋Š” ์ฝ”๋“œ ์˜†์— ์ฃผ์„์œผ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. +- docstring์€ ์„œ์ˆ ํ˜•(`"""Fetches rows from a Bigtable."""`) ๋˜๋Š” ๋ช…๋ นํ˜•(`"""Fetch rows from a Bigtable."""`) ์Šคํƒ€์ผ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ํŒŒ์ผ ๋‚ด์—์„œ ์Šคํƒ€์ผ์€ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- `@property` ์†์„ฑ์˜ docstring์€ ์†์„ฑ์ด๋‚˜ [ํ•จ์ˆ˜ ์ธ์ž](#doc-function-args)์˜ docstring๊ณผ ๊ฐ™์€ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (`"""The Bigtable path."""` ๋Œ€์‹ ์— `"""Returns the Bigtable path."""`). -- ๋‹ค๋งŒ ํ•จ์ˆ˜์˜ ๋ช‡๊ฐ€์ง€ ํŠน์ • ๋ถ€๋ถ„๋“ค์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋ณ„๋„์˜ ํŠน๋ณ„์„น์…˜์œผ๋กœ ๊ธฐ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๊ฐ ์„น์…˜์€ ํ‘œ์ œ๋กœ ์‹œ์ž‘ํ•˜๋ฉฐ ์ฝœ๋ก ์œผ๋กœ ๋๋งบ์Šต๋‹ˆ๋‹ค. -- ๊ฐ ์„น์…˜์€ ํ‘œ์ œ๋ฅผ ์ œ์™ธํ•˜๊ณ  2์นธ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. +- ํ•จ์ˆ˜์˜ ํŠน์ • ์ธก๋ฉด์€ ์•„๋ž˜์— ๋‚˜์—ด๋œ ํŠน๋ณ„ํ•œ ์„น์…˜์—์„œ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๊ฐ ์„น์…˜์€ ์ฝœ๋ก ์œผ๋กœ ๋๋‚˜๋Š” ์ œ๋ชฉ ํ–‰์œผ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. +- ์ œ๋ชฉ์„ ์ œ์™ธํ•œ ๋ชจ๋“  ์„น์…˜์€ 2์นธ ๋˜๋Š” 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์œ ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (ํŒŒ์ผ ๋‚ด์—์„œ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€). +- ํ•จ์ˆ˜์˜ ์ด๋ฆ„๊ณผ ์‹œ๊ทธ๋‹ˆ์ฒ˜๊ฐ€ ์ถฉ๋ถ„ํžˆ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์—ฌ ํ•œ ์ค„์˜ docstring์œผ๋กœ ์ ์ ˆํžˆ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ, ์ด๋Ÿฌํ•œ ์„น์…˜์€ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -1595,12 +1649,13 @@ ##### [_Returns:_ (์ œ๋„ˆ๋ ˆ์ดํ„ฐ์—๋Š” _Yields:_)](#doc-function-returns) -- ๋ฐ˜ํ™˜๊ฐ’์˜ ์ž๋ฃŒํ˜•๊ณผ ์˜๋ฏธ๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ•จ์ˆ˜๊ฐ€ None๋งŒ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋ฉด ์ด ์„น์…˜์€ ํ•„์š”์—†์Šต๋‹ˆ๋‹ค. -- ๋˜ํ•œ ๋งŒ์•ฝ docstring์ด Returns ๋‚˜ Yields๋กœ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜(e.g. `"""Returns row from Bigtable as a tuple of strings."""`) ์ถฉ๋ถ„ํ•œ ์„ค๋ช…์ด ์ œ๊ณต๋œ๋‹ค๋ฉด ์ƒ๋žต ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -- Tuple ๋ฐ˜ํ™˜ ๊ฐ’์„ ๊ฐœ๋ณ„ ์ด๋ฆ„์ด ์žˆ๋Š” ์—ฌ๋Ÿฌ ๋ฐ˜ํ™˜ ๊ฐ’์ธ ๊ฒƒ์ฒ˜๋Ÿผ ์ž์ฃผ ๋ฌธ์„œํ™”ํ•˜๋Š” 'NumPy style' ([example](http://numpy.org/doc/stable/reference/generated/numpy.linalg.qr.html))์„ ๋ชจ๋ฐฉํ•˜์ง€ ๋งˆ์„ธ์š”. (Tuple๋ฅผ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.) -- ๋Œ€์‹ , ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ๊ธฐ์ˆ ํ•˜์„ธ์š”. - - "Returns a tuple (mat_a, mat_b), where mat_a is ..., and ...". -- Docstring์˜ ๋ณด์กฐ ์ด๋ฆ„์€ ํ•จ์ˆ˜ ๋ณธ๋ฌธ์— ์‚ฌ์šฉ๋œ ๋‚ด๋ถ€ ์ด๋ฆ„๊ณผ ๋ฐ˜๋“œ์‹œ ์ผ์น˜ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. (ํ•ด๋‹น ์ด๋ฆ„์€ API์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.) +- ๋ฐ˜ํ™˜ ๊ฐ’์˜ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•˜๊ณ , ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์—์„œ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ํƒ€์ž… ์ •๋ณด๋„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ํ•จ์ˆ˜๊ฐ€ None๋งŒ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ, ์ด ์„น์…˜์€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- docstring์ด "Return", "Returns", "Yield", "Yields"๋กœ ์‹œ์ž‘ํ•˜๊ณ (e.g. `"""Returns row from Bigtable as a tuple of strings."""`), ์ฒซ ๋ฒˆ์งธ ๋ฌธ์žฅ์ด ๋ฐ˜ํ™˜ ๊ฐ’์„ ์„ค๋ช…ํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•  ๊ฒฝ์šฐ, ์ด ์„น์…˜์€ ์ƒ๋žต๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- ์ด์ „์˜ 'NumPy ์Šคํƒ€์ผ'์„ ๋ชจ๋ฐฉํ•˜์ง€ ๋งˆ์„ธ์š”. ([example](https://numpy.org/doc/1.24/reference/generated/numpy.linalg.qr.html)) ์ด ์Šคํƒ€์ผ์€ ์ข…์ข… ํŠœํ”Œ ๋ฐ˜ํ™˜ ๊ฐ’์„ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐœ๋ณ„ ๋ฐ˜ํ™˜ ๊ฐ’์ฒ˜๋Ÿผ ๊ฐ๊ฐ์˜ ์ด๋ฆ„์œผ๋กœ ๋ฌธ์„œํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค. (ํŠœํ”Œ์ด๋ผ๋Š” ์ ์„ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š๊ณ ) +- ๋Œ€์‹ , ๋ฐ˜ํ™˜ ๊ฐ’์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๋ช…ํ•˜์„ธ์š”: "Returns: A tuple (mat_a, mat_b), where mat_a is ..., and ...". +- docstring์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์„ค๋ช…์šฉ ์ด๋ฆ„์€ ํ•จ์ˆ˜ ๋ณธ๋ฌธ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋‚ด๋ถ€ ์ด๋ฆ„๊ณผ ๋ฐ˜๋“œ์‹œ ์ผ์น˜ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค (๋‚ด๋ถ€ ์ด๋ฆ„์€ API์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค) +- ํ•จ์ˆ˜๊ฐ€ `yield`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ(์ฆ‰, ์ œ๋„ˆ๋ ˆ์ดํ„ฐ์ธ ๊ฒฝ์šฐ), `Yields:` ์„น์…˜์—์„œ๋Š” ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋กœ ๋ฐ˜ํ™˜๋˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ, `next()`์— ์˜ํ•ด ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -1611,10 +1666,11 @@ - ๋ช…์‹œ๋œ API๊ฐ€ docstring์„ ์œ„๋ฐ˜ํ–ˆ์„ ๋  ๊ฒฝ์šฐ, ์˜ˆ์™ธ๋ฅผ ๋ฌธ์„œํ™”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. (์™œ๋ƒํ•˜๋ฉด ์ด๊ฒƒ์€ ์—ญ์„ค์ ์œผ๋กœ API์˜ API๋ฅผ ์œ„๋ฐ˜ํ•˜๋Š” ํ–‰๋™์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.) ```python - def fetch_smalltable_rows(table_handle: smalltable.Table, - keys: Sequence[Union[bytes, str]], - require_all_keys: bool = False, - ) -> Mapping[bytes, Tuple[str, ...]]: + def fetch_smalltable_rows( + table_handle: smalltable.Table, + keys: Sequence[bytes | str], + require_all_keys: bool = False, + ) -> Mapping[bytes, tuple[str, ...]]: """Fetches rows from a Smalltable. Retrieves rows pertaining to the given keys from the Table instance @@ -1648,10 +1704,11 @@ - ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ์ค„ ๋ฐ”๊ฟˆ์ด ์žˆ๋Š” `Args:`๋„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ```python - def fetch_smalltable_rows(table_handle: smalltable.Table, - keys: Sequence[Union[bytes, str]], - require_all_keys: bool = False, - ) -> Mapping[bytes, Tuple[str, ...]]: + def fetch_smalltable_rows( + table_handle: smalltable.Table, + keys: Sequence[bytes | str], + require_all_keys: bool = False, + ) -> Mapping[bytes, tuple[str, ...]]: """Fetches rows from a Smalltable. Retrieves rows pertaining to the given keys from the Table instance @@ -1684,19 +1741,51 @@ """ ``` + + + +##### 3.8.3.1 Overridden Methods + +- ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” [`@override`](https://typing-extensions.readthedocs.io/en/latest/#override) ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ(`typing_extensions` ๋˜๋Š” `typing` ๋ชจ๋“ˆ์—์„œ ์ œ๊ณต)๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ docstring์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- ๋‹จ, ์˜ค๋ฒ„๋ผ์ด๋”ฉ๋œ ๋ฉ”์„œ๋“œ์˜ ๋™์ž‘์ด ๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ์˜ ๊ณ„์•ฝ์„ ์‹ค์งˆ์ ์œผ๋กœ ๊ฐœ์„ ํ•˜๊ฑฐ๋‚˜, ์ถ”๊ฐ€์ ์ธ ์‚ฌ์ด๋“œ ์ž„ํŽ™ํŠธ ๋“ฑ์„ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š”, ๊ทธ๋Ÿฌํ•œ ์ฐจ์ด์ ์ด ์ตœ์†Œํ•œ ํฌํ•จ๋œ docstring์ด ์˜ค๋ฒ„๋ผ์ด๋”ฉ ๋ฉ”์„œ๋“œ์— ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + + ```python + from typing_extensions import override + class Parent: + def do_something(self): + """Parent method, includes docstring.""" + # ์ž์‹ ํด๋ž˜์Šค, ์˜ค๋ฒ„๋ผ์ด๋“œ๋กœ ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ๋ฉ”์„œ๋“œ. + class Child(Parent): + @override + def do_something(self): + pass + ``` + + ```python + # ์ž์‹ ํด๋ž˜์Šค์—์„œ @override ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ, docstring์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + class Child(Parent): + def do_something(self): + pass + # docstring์ด ๋‹จ์ˆœํ•œ ๊ฒฝ์šฐ, @override๋งŒ์œผ๋กœ๋„ ๋ฌธ์„œ๊ฐ€ ๊ธฐ๋ณธ ํด๋ž˜์Šค์— ์žˆ์Œ์„ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + class Child(Parent): + @override + def do_something(self): + """See base class.""" + ``` + #### 3.8.4 Classes - ํด๋ž˜์Šค๋Š” ์„ ์–ธ ๋ฐ”๋กœ ์•„๋ž˜์— ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์„ค๋ช…ํ•˜๋Š” docstring ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋งŒ์•ฝ ํด๋ž˜์Šค๊ฐ€ public attributes ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด [function's `Args`](#doc-function-args) ์„น์…˜๊ณผ ๊ฐ™์€ ํ˜•์‹์„ ์‚ฌ์šฉํ•ด `Attributes` ์„น์…˜์„ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- [properties](#properties)์„ ์ œ์™ธํ•œ ๊ณต๊ฐœ ์†์„ฑ์€ `Attributes` ์„น์…˜์—์„œ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•˜๋ฉฐ, [ํ•จ์ˆ˜์˜ `Args`](#doc-function-args) ์„น์…˜๊ณผ ๋™์ผํ•œ ํ˜•์‹์„ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ```python class SampleClass: """Summary of class here. - Longer class information.... - Longer class information.... + Longer class information... + Longer class information... Attributes: likes_spam: A boolean indicating if we like SPAM or not. @@ -1704,14 +1793,42 @@ class SampleClass: """ def __init__(self, likes_spam: bool = False): - """Inits SampleClass with blah.""" + """Initializes the instance based on spam preference. + Args: + likes_spam: Defines if instance exhibits this preference. + """ self.likes_spam = likes_spam self.eggs = 0 - def public_method(self): - """Performs operation blah.""" + @property + def butter_sticks(self) -> int: + """The number of butter sticks we have.""" ``` +- ๋ชจ๋“  ํด๋ž˜์Šค์˜ docstring์€ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฌด์—‡์„ ๋‚˜ํƒ€๋‚ด๋Š”์ง€๋ฅผ ์„ค๋ช…ํ•˜๋Š” ํ•œ ์ค„ ์š”์•ฝ์œผ๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” `Exception`์˜ ์„œ๋ธŒํด๋ž˜์Šค๋„ ์˜ˆ์™ธ๊ฐ€ ๋ฌด์—‡์„ ๋‚˜ํƒ€๋‚ด๋Š”์ง€๋ฅผ ์„ค๋ช…ํ•ด์•ผ ํ•˜๋ฉฐ, ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•ด์„œ๋Š” ์„ค๋ช…ํ•˜์ง€ ์•Š์•„์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ํด๋ž˜์Šค์˜ docstring์€ ํด๋ž˜์Šค๊ฐ€ ํด๋ž˜์Šค๋ผ๋Š” ๋“ฑ์˜ ๋ถˆํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. + +- ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ + + ```python + class CheeseShopAddress: + """The address of a cheese shop. + ... + """ + class OutOfCheeseError(Exception): + """No more cheese is available.""" + ``` + +- ๋ถ€์ ์ ˆํ•œ ์˜ˆ + + ```python + class CheeseShopAddress: + """Class that describes the address of a cheese shop. + ... + """ + class OutOfCheeseError(Exception): + """Raised when no more cheese is available.""" + ``` + @@ -1762,25 +1879,24 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. ### 3.10 Strings - ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋ชจ๋‘ ๋ฌธ์ž์—ด์ธ ๊ฒฝ์šฐ์—๋„ [f-string](https://docs.python.org/3/reference/lexical_analysis.html#f-strings), `format` ๋ฉ”์†Œ๋“œ๋‚˜ `%` ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํฌ๋ฉ”ํŒ…ํ•˜์„ธ์š”. -- ๋ฌผ๋ก  `+` ๋‚˜ `%` (๋˜๋Š” `format`) ๋ฅผ ์–ธ์ œ ์‚ฌ์šฉํ• ์ง€๋Š” ๊ฐœ๋ฐœ์ž์˜ ํŒ๋‹จ์— ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. -- ๋ฌธ์ž์—ด์„ ํ•ฉ์น˜๊ธฐ ์œ„ํ•ด `%` ๋˜๋Š” `format`์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. +- ๋ฌธ์ž์—ด ํฌ๋งทํŒ… ์˜ต์…˜ ์‚ฌ์ด์—์„œ ์ตœ์ƒ์˜ ํŒ๋‹จ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- `+`๋ฅผ ์‚ฌ์šฉํ•œ ๋‹จ์ผ join์€ ๊ดœ์ฐฎ์ง€๋งŒ, `+`๋ฅผ ์‚ฌ์šฉํ•œ ํฌ๋งทํŒ…์€ ํ”ผํ•˜์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - x = a + b + x = f'name: {name}; score: {n}' x = '%s, %s!' % (imperative, expletive) x = '{}, {}'.format(first, second) x = 'name: %s; score: %d' % (name, n) + x = 'name: %(name)s; score: %(score)d' % {'name':name, 'score':n} x = 'name: {}; score: {}'.format(name, n) - x = f'name: {name}; score: {n}' + x = a + b ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - x = '%s%s' % (a, b) # use + in this case - x = '{}{}'.format(a, b) # use + in this case x = first + ', ' + second x = 'name: ' + name + '; score: ' + str(n) ``` @@ -1868,6 +1984,9 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. will collapse common leading spaces in each line.""") ``` +- ์—ฌ๊ธฐ์„œ ๋ฐฑ์Šฌ๋ž˜์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ [๋ช…์‹œ์ ์ธ ์ค„ ์ด์–ด์“ฐ๊ธฐ](#line-length)์— ๋Œ€ํ•œ ๊ธˆ์ง€๋ฅผ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- ์ด ๊ฒฝ์šฐ, ๋ฐฑ์Šฌ๋ž˜์‹œ๋Š” ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์—์„œ [์ค„๋ฐ”๊ฟˆ์„ ์ด์Šค์ผ€์ดํ”„](https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals)ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + #### 3.10.1 Logging @@ -1918,7 +2037,7 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. ```python ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ: if not 0 <= p <= 1: - raise ValueError(f'Not a probability: {p!r}') + raise ValueError(f'Not a probability: {p=}') try: os.rmdir(workdir) except OSError as error: @@ -1929,7 +2048,7 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. ```python ์ž˜๋ชป๋œ ์˜ˆ: if p < 0 or p > 1: # PROBLEM: also false for float('nan')! - raise ValueError(f'Not a probability: {p!r}') + raise ValueError(f'Not a probability: {p=}') try: os.rmdir(workdir) except OSError: @@ -2004,33 +2123,44 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. - ์ž„์‹œ์ , ์ž ์‹œ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์ฝ”๋“œ ๋˜๋Š” ์ข‹๊ธฐ๋Š” ํ•˜์ง€๋งŒ ์™„๋ฒฝํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ `TODO` ์ฃผ์„์„ ์‚ฌ์šฉํ•˜์„ธ์š”. -- `TODO` ์ฃผ์„์€ ๋Œ€๋ฌธ์ž๋กœ ๋˜์–ด์žˆ๋Š” `TODO` ๋ฌธ๊ตฌ๋กœ ์‹œ์ž‘ํ•˜๋ฉฐ ํ•ด๋‹น ์ฝ”๋“œ์— ๋Œ€ํ•œ ๊ฐ€์žฅ ๋†’์€ ์ดํ•ด๋„๋ฅผ ๊ฐ€์ง„ ์ธ๋ฌผ์˜ ์ด๋ฆ„, ์ด๋ฉ”์ผ ์ฃผ์†Œ ๋˜๋Š” ๋‹ค๋ฅธ ์‹ ์›๊ตฌ๋ถ„ ๋ฌธ๊ตฌ๋ฅผ ๊ด„ํ˜ธ์•ˆ์— ๋„ฃ์–ด ํฌํ•จํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์ด๊ฒƒ ๋’ค์— ๋ฌด์—‡์„ ํ•ด์•ผํ•˜๋Š” ์ง€์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. +- `TODO` ์ฃผ์„์€ ๋ชจ๋‘ ๋Œ€๋ฌธ์ž๋กœ ๋œ `TODO`๋กœ ์‹œ์ž‘ํ•˜๊ณ , ๋‹ค์Œ์— ์ฝœ๋ก ์„ ๋ถ™์ด๋ฉฐ, ๋งฅ๋ฝ์ด ํฌํ•จ๋œ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ๋งํฌ(์ด์ƒ์ ์œผ๋กœ๋Š” ๋ฒ„๊ทธ ์ฐธ์กฐ)๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๋ฒ„๊ทธ ์ฐธ์กฐ๊ฐ€ ์„ ํ˜ธ๋ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋ฒ„๊ทธ๋Š” ์ถ”์ ๋˜๋ฉฐ ํ›„์† ๋Œ“๊ธ€์ด ๋‹ฌ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +- ์ด ๋ฌธ๋งฅ ๋‹ค์Œ์— ํ•˜์ดํ”ˆ `-`์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์„ค๋ช… ๋ฌธ์ž์—ด์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”.. +- ๋ชฉ์ ์€ ์ผ๊ด€๋œ `TODO` ํ˜•์‹์„ ์œ ์ง€ํ•˜์—ฌ, ๋” ๋งŽ์€ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. -- ๋ชฉ์ ์€ `TODO`๊ฐ€ ์ผ๊ด€๋œ ํ˜•์‹์„ ์ด์šฉํ•˜์—ฌ ์ถ”ํ›„ ํ•„์š”ํ•œ ์„ธ๋ถ€์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. -- `TODO` ๋Š” ๋ณธ์ธ์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ฒ ๋‹ค๋Š” ์•ฝ์†์ด ์•„๋‹™๋‹ˆ๋‹ค. -- ๋”ฐ๋ผ์„œ `TODO` ๋ฅผ ๋งŒ๋“œ์…จ๋‹ค๋ฉด ๊ฑฐ์˜ ํ•ญ์ƒ ์ž‘์„ฑํ•œ ๋ณธ์ธ์˜ ์ด๋ฆ„์ด ๋“ค์–ด๊ฐ€์•ผ ํ•ฉ๋‹ˆ๋‹ค. + ```python + # TODO: crbug.com/192795 - Investigate cpufreq optimizations. + ``` -```python -# TODO(kl@gmail.com): Use a "*" here for string repetition. -# TODO(Zeke) Change this to use relations. -``` +- ์ด์ „ ์Šคํƒ€์ผ๋กœ, ์˜ˆ์ „์—๋Š” ๊ถŒ์žฅ๋˜์—ˆ์ง€๋งŒ ์ƒˆ๋กœ์šด ์ฝ”๋“œ์—์„œ๋Š” ์‚ฌ์šฉ์ด ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + + ```python + # TODO(crbug.com/192795): Investigate cpufreq optimizations. + # TODO(yourusername): Use a "\*" here for concatenation operator. + ``` + +- ๋ฌธ๋งฅ์œผ๋กœ ๊ฐœ์ธ์ด๋‚˜ ํŒ€์„ ์ฐธ์กฐํ•˜๋Š” TODO๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜์„ธ์š”. + + ```python + # TODO: @yourusername - File an issue and use a '*' for repetition. + ``` -- ๋งŒ์•ฝ ์ž‘์„ฑํ•œ `TODO` ๊ฐ€ "์ถ”ํ›„ ๋ฌด์—‡์„ ์ง„ํ–‰ํ•  ๊ฒƒ" ์ด๋ผ๋Š” ํ˜•์‹์„ ๋‹ด๊ณ  ์žˆ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ("2009๋…„ 11์›”๊นŒ์ง€") ์™€ ๊ฐ™์€ ๊ตฌ์ฒด์ ์ธ ๊ธฐ๊ฐ„์ด๋‚˜ ("๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ๊ฐ€ XML ์š”์ฒญ์„ ํ•ด๊ฒฐ ํ• ์ˆ˜ ์žˆ์„๋•Œ ์ด ์ฝ”๋“œ ์‚ญ์ œ") ์ฒ˜๋Ÿผ ๋ชฉ์ ์„ ํฌํ•จํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- `TODO`๊ฐ€ "๋ฏธ๋ž˜์˜ ์–ด๋Š ์‹œ์ ์— ๋ฌด์—‡์„ ํ•ด์•ผ ํ•œ๋‹ค"๋Š” ํ˜•์‹์ด๋ผ๋ฉด, ๋ฏธ๋ž˜์˜ ์ฝ”๋“œ ์œ ์ง€ ๊ด€๋ฆฌ์ž๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งค์šฐ ๊ตฌ์ฒด์ ์ธ ๋‚ ์งœ("2009๋…„ 11์›”๊นŒ์ง€")๋‚˜ ์‚ฌ๊ฑด("๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ๊ฐ€ XML ์š”์ฒญ์„ ํ•ด๊ฒฐ ํ• ์ˆ˜ ์žˆ์„๋•Œ ์ด ์ฝ”๋“œ ์‚ญ์ œ")์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์ด์Šˆ๋Š” ์ด๋ฅผ ์ถ”์ ํ•˜๋Š” ๋ฐ ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค. --- ### 3.13 import ํ˜•์‹ -- imports๋Š” ๊ฐœ๋ณ„์ ์ธ ๋ผ์ธ์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค; [`typing` imports์— ๋Œ€ํ•œ ์˜ˆ์™ธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.](#s3.19.12-imports). +- imports๋Š” ๊ฐœ๋ณ„์ ์ธ ๋ผ์ธ์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค; [`typing` ๊ทธ๋ฆฌ๊ณ  `collections.abc` imports์— ๋Œ€ํ•œ ์˜ˆ์™ธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.](#s3.19.12-imports). - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python import os import sys - from typing import Mapping, Sequence + from typing import Any, NewType ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ @@ -2042,7 +2172,15 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. - import๋Š” ๋ชจ๋“ˆ์˜ ์ฃผ์„ ๊ณผ docstring ๋ฐ”๋กœ ๋‹ค์Œ, ๋ชจ๋“ˆ ์ „์—ญ ๋ฐ ์ƒ์ˆ˜ ๋ฐ”๋กœ ์•ž ํŒŒ์ผ์˜ ๋งจ ์œ„์— ๋ฐฐ์น˜๋ฉ๋‹ˆ๋‹ค. - import๋Š” ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๊ฒƒ ๋ถ€ํ„ฐ ์ตœ์†Œํ•œ์˜ ์ผ๋ฐ˜์ ์ธ ๊ฒƒ๋“ค๊นŒ์ง€ ๋ฌถ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -1. ํŒŒ์ด์ฌ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ +1. Python์˜ **future** import ๋ฌธ + + ```python + from __future__ import annotations + ``` + + ์ž์„ธํ•œ ๋‚ด์šฉ์€ [์œ„](#from-future-imports)๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. + +2. ํŒŒ์ด์ฌ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ - import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -2050,7 +2188,7 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. import sys ``` -2. [third-party](https://pypi.org/) +3. [third-party](https://pypi.org/) - ๋ชจ๋“ˆ์ด๋‚˜ ํŒจํ‚ค์ง€์˜ import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -2058,7 +2196,7 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. import tensorflow as tf ``` -3. Code repository +4. Code repository - ์„œ๋ธŒ ํŒจํ‚ค์ง€์˜ import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -2066,7 +2204,7 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. from otherproject.ai import mind ``` -4. ๋™์ผํ•œ top ๋ ˆ๋ฒจ์— ์†ํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํŠน์ •์„ importํ•˜๋Š” ๊ฒƒ์€ **๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค** +5. ๋™์ผํ•œ top ๋ ˆ๋ฒจ์— ์†ํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํŠน์ •์„ importํ•˜๋Š” ๊ฒƒ์€ **๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค** - ์„œ๋ธŒ ํŒจํ‚ค์ง€์˜ ํŒŒ์ผ import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -2164,7 +2302,9 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. `global_var_name`, `instance_var_name`, `function_parameter_name`, -`local_var_name`. +`local_var_name`, +`query_proper_noun_for_thing`, +`send_acronym_via_https`. - ํ•จ์ˆ˜ ์ด๋ฆ„, ๋ณ€์ˆ˜ ์ด๋ฆ„, ๊ทธ๋ฆฌ๊ณ  ํŒŒ์ผ ์ด๋ฆ„์€ ์„ค๋ช…์ ์ด์—ฌ์•ผ ํ•˜๊ณ  ์•ฝ์–ด๋กœ ์ ๋Š” ์ผ์„ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ํŠนํžˆ ๋ชจํ˜ธํ•˜๊ฑฐ๋‚˜ ํ”„๋กœ์ ํŠธ์— ์ฐธ์—ฌํ•˜์ง€ ์•Š์€ ์‚ฌ๋žŒ๋“ค์ด ์ฝ์—ˆ์„ ๋•Œ ์ต์ˆ™ํ•˜์ง€ ์•Š์€ ์•ฝ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งˆ์„ธ์š”. ๊ทธ๋ฆฌ๊ณ  ์ ˆ๋Œ€ ๋‹จ์–ด์—์„œ ๊ธ€์ž๋ฅผ ์ง€์›Œ ์ค„์ด์ง€ ๋งˆ์„ธ์š”. @@ -2175,15 +2315,20 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. #### 3.16.1 ํ”ผํ•ด์•ผ ํ•  ์ด๋ฆ„ -1. ์•„๋ž˜์™€ ๊ฐ™์€ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•œ ๋‹จ์ผ ๊ธ€์ž๋Š” ํ”ผํ•ฉ๋‹ˆ๋‹ค. +- ์•„๋ž˜์™€ ๊ฐ™์€ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•œ ๋‹จ์ผ ๊ธ€์ž๋Š” ํ”ผํ•ฉ๋‹ˆ๋‹ค. + + - counters์ด๋‚˜ iterators์—์„œ ์‚ฌ์šฉํ•  ๋•Œ (์˜ˆ. `i`, `j`, `k`, `v` ๋“ฑ) + - `try/except`๋ฌธ์—์„œ ์˜ˆ์™ธ ์‹๋ณ„์ž๋กœ `e`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ + - with๋ฌธ์˜ ํŒŒ์ผ ํ•ธ๋“ค์—์„œ `f`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ + - ์ œ์•ฝ ์กฐ๊ฑด์ด ์—†๋Š” ๋น„๊ณต์‹์ ์ธ [type variables](#typing-type-var)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ (e.g., `_T = TypeVar("_T"), _P = ParamSpec("_P")`) -- counters์ด๋‚˜ iterators์—์„œ ์‚ฌ์šฉํ•  ๋•Œ (์˜ˆ. `i`, `j`, `k`, `v` ๋“ฑ) -- `try/except`๋ฌธ์—์„œ ์˜ˆ์™ธ ์‹๋ณ„์ž๋กœ `e`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ -- with๋ฌธ์˜ ํŒŒ์ผ ํ•ธ๋“ค์—์„œ `f`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋‹จ์ผ ๊ธ€์ž๋ฅผ ๋‚จ์šฉํ•˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋งํ•ด์„œ ์„œ์ˆ ์„ฑ์€ ์ด๋ฆ„์˜ ๊ฐ€์‹œ์„ฑ ๋ฒ”์œ„์— ๋น„๋ก€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `i`๋Š” 5ํ–‰ ์ฝ”๋“œ ๋ธ”๋ก์— ์ ํ•ฉํ•œ ์ด๋ฆ„์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ค‘์ฒฉ๋œ ์—ฌ๋Ÿฌ ๋ฒ”์œ„ ๋‚ด์—์„œ๋Š” ๋„ˆ๋ฌด ๋ชจํ˜ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + - package/module ์ด๋ฆ„์—์„œ dashes(`-`)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ - `__์ด์ค‘_์„ ํ–‰_๋ฐ_ํ›„ํ–‰_๋ฐ‘์ค„__` ์ด๋ฆ„์„ ์‚ฌ์šฉํ•  ๋•Œ (Python์—์„œ ์˜ˆ์•ฝ์–ด) + - ์›๋ณธ์— ์—†๋Š” ์ถ”๊ฐ€ ์„ค๋ช… : double leading and trailing underscore : (์•ž ๋’ค๋กœ \_๊ฐ€ 2๊ฐœ์”ฉ ์žˆ๋Š”๊ฒƒ e.g **name**, **init**) + - ๊ณต๊ฒฉ์ ์ธ ๋‹จ์–ด - ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ณ€์ˆ˜ ํƒ€์ž…์„ ํฌํ•จํ•˜๋Š” ์ด๋ฆ„ (์˜ˆ : `id_to_name_dict`) @@ -2195,16 +2340,20 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. - "Internal"๋Š” ๋ชจ๋“ˆ์˜ ๋‚ด๋ถ€ ๋˜๋Š” ํด๋ž˜์Šค ๋‚ด์—์„œ protected ๋˜๋Š” private๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. - ๋‹จ์ผ ๋ฐ‘์ค„(`_`)์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ชจ๋“ˆ ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜๋ฅผ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ง€์›์ด ์žˆ์Šต๋‹ˆ๋‹ค. (linters๋Š” ๋ณดํ˜ธ๋œ ๋ฉค๋ฒ„ ์ ‘๊ทผ์— ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.) +- ๋‹จ์ผ ์–ธ๋”์Šค์ฝ”์–ด(`_`)๋ฅผ ์ ‘๋‘์‚ฌ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ชจ๋“ˆ ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜ ๋ณดํ˜ธ๋ฅผ ์œ„ํ•œ ์ผ๋ถ€ ์ง€์›์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค (linters๊ฐ€ ๋ณดํ˜ธ๋œ ๋ฉค๋ฒ„ ์ ‘๊ทผ์„ ๊ฒฝ๊ณ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค). ๊ทธ๋Ÿฌ๋‚˜ ์œ ๋‹› ํ…Œ์ŠคํŠธ๊ฐ€ ํ…Œ์ŠคํŠธ ์ค‘์ธ ๋ชจ๋“ˆ์˜ ๋ณดํ˜ธ๋œ ์ƒ์ˆ˜์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์€ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. - ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋‚˜ ๋ฉ”์†Œ๋“œ์— ์ด์ค‘ ๋ฐ‘์ค„(`__` : dunder)์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ณ€์ˆ˜๋‚˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•ด๋‹น ํด๋ž˜์Šค์— ๋Œ€ํ•ด ํšจ๊ณผ์ ์œผ๋กœ private ๋ฉ๋‹ˆ๋‹ค. - ๊ฐ€๋…์„ฑ๊ณผ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ์„ฑ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ณ  _์‹ค์ œ๋กœ_ ๋น„๊ณต๊ฐœ๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. - ํ•˜๋‚˜์˜ ๋ฐ‘์ค„์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. - ๋ชจ๋“ˆ์— ๊ด€๋ จ ํด๋ž˜์Šค์™€ top-level ํ•จ์ˆ˜๋ฅผ ํ•จ๊ป˜ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. - ์ž๋ฐ”์™€๋Š” ๋‹ค๋ฅด๊ฒŒ ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ์— ๋Œ€ํ•ด ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋กœ ์ œํ•œ์„ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. - CapWords(๋‹จ์–ด์˜ ์ฒซ ๊ธ€์ž๋ฅผ ๋Œ€๋ฌธ์ž๋กœ ํ•˜๋Š” ๋ฐฉ์‹)์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์ด \_with_under.py ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ์†Œ๋ฌธ์ž๋กœ ํ•ฉ๋‹ˆ๋‹ค. + - ๋น„๋ก ๋ช‡๋ช‡ ์˜ค๋ž˜๋œ ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์ด CapWords.py์ผ์ง€๋ผ๋„ ์ด์ œ๋Š” ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์„ class์ด๋ฆ„์— ๋”ฐ๋ผ ์ง“๊ฒŒ ๋˜๋ฉด ํ˜ผ๋ž€์Šค๋Ÿฌ์šฐ๋ฏ€๋กœ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. (e.g "์ž ๊น๋งŒ, -- ๋‚ด๊ฐ€ `import StringIO`๋ฅผ ํ•œ๊ฑฐ์•ผ ์•„๋‹ˆ๋ฉด `from StringIO import StringIO`๋ฅผ ํ•œ๊ฑฐ์•ผ ?" ๊ฐ™์€ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.) -- ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ CapWord๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ "test"๋กœ ์‹œ์ž‘ํ•˜๋Š” _unittest_ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์— Undercore๊ฐ€ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - - ํ•œ ๊ฐ€์ง€ ๊ฐ€๋Šฅํ•œ ํŒจํ„ด์€ `test_`๋กœ, ์˜ˆ๋ฅผ ๋“ค์–ด `testPop_EmptyStack`๊ฐ™์€ ํŒจํ„ด์€ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. - - test ๋ฉ”์„œ๋“œ์— ์— ์ด๋ฆ„์„ ๋ถ™์ด๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•์€ ์—†์Šต๋‹ˆ๋‹ค. + +- ์ƒˆ๋กœ์šด ์œ ๋‹› ํ…Œ์ŠคํŠธ ํŒŒ์ผ์€ PEP 8์„ ์ค€์ˆ˜ํ•˜๋Š” ์†Œ๋ฌธ์ž์™€ ์–ธ๋”์Šค์ฝ”์–ด ๋ฐฉ์‹์˜ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. + - ์˜ˆ๋ฅผ ๋“ค์–ด, `test**`์™€ ๊ฐ™์€ ํ˜•์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + - ์ผ๊ด€์„ฑ์„ ์œ„ํ•ด(\*) ์ด์ „ ๋ชจ๋“ˆ์—์„œ CapWords ํ•จ์ˆ˜ ์ด๋ฆ„์„ ๋”ฐ๋ฅด๋Š” ๊ฒฝ์šฐ, `test`๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ด๋ฆ„์— ๋…ผ๋ฆฌ์  ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด ์–ธ๋”์Šค์ฝ”์–ด๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + - ํ•˜๋‚˜์˜ ๊ฐ€๋Šฅํ•œ ํŒจํ„ด์€ `test_`์ž…๋‹ˆ๋‹ค. @@ -2304,9 +2453,24 @@ if __name__ == '__main__': #### 3.19.1 ์ผ๋ฐ˜์ ์ธ ๊ทœ์น™ -- [PEP-484](https://www.python.org/dev/peps/pep-0484/)์„ ์ฝ์œผ์„ธ์š”. -- ๋ฉ”์„œ๋“œ์—์„œ๋Š” `self`, `cls`๋Š” Type์˜ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—์„œ๋งŒ ์ฃผ์„์„ ๋‹ฌ์•„์•ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ) `@classmethod def create(cls: Type[T]) -> T: return cls()` +- [PEP-484](https://peps.python.org/pep-0484/)์„ ์ฝ์œผ์„ธ์š”. + +- `self` ๋˜๋Š” `cls`์— ์ฃผ์„์„ ๋‹ฌ ํ•„์š”๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์—†์Šต๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ ํƒ€์ž… ์ •๋ณด๋ฅผ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ [`Self`](https://docs.python.org/3/library/typing.html#typing.Self)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + ```python + from typing import Self + class BaseClass: + @classmethod + def create(cls) -> Self: + ... + def difference(self, other: Self) -> float: + ... + ``` + +- ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, `__init__`์˜ ๋ฐ˜ํ™˜ ๊ฐ’์— ์ฃผ์„์„ ๋‹ฌ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค (์—ฌ๊ธฐ์„œ `None`๋งŒ ์œ ํšจํ•œ ์˜ต์…˜์ž…๋‹ˆ๋‹ค). + - ๋ชจ๋“  ๋ณ€์ˆ˜๋‚˜ ๋ฐ˜ํ™˜๋˜๋Š” Type์ด ์ •ํ•ด์ง€์ง€ ์•Š์•˜๋‹ค๋ฉด `Any`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + - ๋ชจ๋“ˆ์—์„œ ๋ชจ๋“  ํ•จ์ˆ˜์— ์ฃผ์„์„ ๋‹ฌ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. - Public API์—๋Š” ์ตœ์†Œํ•œ์˜ ์ฃผ์„์„ ๋‹ต๋‹ˆ๋‹ค. - ํŒ๋‹จ๋ ฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•œํŽธ์œผ๋กœ๋Š” ์•ˆ์ „์„ฑ๊ณผ ๋ช…ํ™•์„ฑ, ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ํ•œํŽธ์œผ๋กœ๋Š” ์œ ์—ฐ์„ฑ ์‚ฌ์ด์˜ ๊ท ํ˜•์„ ์ž˜ ์žก์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -2321,12 +2485,15 @@ if __name__ == '__main__': - ๊ธฐ์กด์˜ [๋“ค์—ฌ์“ฐ๊ธฐ](#s3.4-indentation) ๊ทœ์น™์„ ๋”ฐ๋ฅด์„ธ์š”. - ์ฃผ์„์ฒ˜๋ฆฌํ•˜๊ณ ๋‚˜์„œ ๋งŽ์€ ํ•จ์ˆ˜๋Š” "ํ•œ ์ค„์— ํ•˜๋‚˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ"๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +- ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ๋ณ„๋„์˜ ์ค„์— ํ‘œ์‹œ๋˜๋„๋ก ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด, ๋งˆ์ง€๋ง‰ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋’ค์— ์‰ผํ‘œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python - def my_method(self, - first_var: int, - second_var: Foo, - third_var: Optional[Bar]) -> int: + def my_method( + self, + first_var: int, + second_var: Foo, + third_var: Bar | None, + ) -> int: ... ``` @@ -2338,23 +2505,25 @@ if __name__ == '__main__': ``` - ํ•จ์ˆ˜ ์ด๋ฆ„, ๋งˆ์ง€๋ง‰ ๋งค๊ฐœ ๋ณ€์ˆ˜ ๋ฐ ๋ฆฌํ„ด Type์˜ ์กฐํ•ฉ์ด ๋„ˆ๋ฌด ๊ธธ๋ฉด ์ƒˆ ํ–‰์—์„œ 4๋งŒํผ ๋“ค์—ฌ ์“ฐ๊ธฐ๋ฉ๋‹ˆ๋‹ค. +- ์ค„ ๋ฐ”๊ฟˆ์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๋ณ„๋„์˜ ์ค„์— ๋ฐฐ์น˜ํ•˜๊ณ , ๋‹ซ๋Š” ๊ด„ํ˜ธ๋ฅผ `def`์™€ ์ •๋ ฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ```python def my_method( - self, first_var: int) -> Tuple[MyLongType1, MyLongType1]: + self, + other_arg: MyLongType | None, + ) -> tuple[MyLongType1, MyLongType1]: ... ``` -๋ฆฌํ„ด ์œ ํ˜•์ด ๋งˆ์ง€๋ง‰ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๊ฐ™์€ ๋ผ์ธ์— ๋งž์ง€ ์•Š์„ ๊ฒฝ์šฐ, ์„ ํ˜ธ๋˜๋Š” ๋ฐฉ๋ฒ•์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ 4๋งŒํผ ์ƒˆ ๋ผ์ธ์— ๋“ค์—ฌ์“ฐ๊ณ  ๋‹ซํžˆ๋Š” ๊ด„ํ˜ธ๋ฅผ "def"์™€ ์ •๋ ฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค. +- ์„ ํƒ์ ์œผ๋กœ, ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๋งˆ์ง€๋ง‰ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๊ฐ™์€ ์ค„์— ๋ฐฐ์น˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -- ๋ฐ˜ํ™˜ Type์ด ๋งˆ์ง€๋ง‰ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๊ฐ™์€ ์ค„์ด ์•„๋‹ ๋•Œ, ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ 4๋งŒํผ ์ƒˆ ๋ผ์ธ์— ๋“ค์—ฌ์“ฐ๊ณ  ๋‹ซํžˆ๋Š” ๊ด„ํ˜ธ๋ฅผ `def`์™€ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค. - - - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ + - ๊ดœ์ฐฎ์€ ์˜ˆ ```python def my_method( - self, **kw_args: Optional[MyLongType] - ) -> Dict[OtherLongType, MyLongType]: + self, + first_var: int, + second_var: int) -> dict[OtherLongType, MyLongType]: ... ``` @@ -2364,8 +2533,8 @@ if __name__ == '__main__': ```python def my_method(self, - **kw_args: Optional[MyLongType] - ) -> Dict[OtherLongType, MyLongType]: + other_arg: MyLongType | None, + ) -> dict[OtherLongType, MyLongType]: ... ``` @@ -2375,10 +2544,11 @@ if __name__ == '__main__': ```python def my_method( self, - first_var: Tuple[List[MyLongType1], - List[MyLongType2]], - second_var: List[Dict[ - MyLongType3, MyLongType4]]) -> None: + first_var: tuple[list[MyLongType1], + list[MyLongType2]], + second_var: list[dict[ + MyLongType3, MyLongType4]], + ) -> None: ... ``` @@ -2409,23 +2579,34 @@ if __name__ == '__main__': #### 3.19.3 ์ „๋ฐฉ์„ ์–ธ -- ์•„์ง ์ •์˜๋˜์ง€ ์•Š์€ ๋™์ผํ•œ ๋ชจ๋“ˆ์˜ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ(์˜ˆ, ํด๋ž˜์Šค ์„ ์–ธ ๋‚ด์— ํด๋ž˜์Šค๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋˜๋Š” ์•„๋ž˜์— ์ •์˜๋œ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ) `from __future__ import annotations`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ์—๋Š” ์ฃผ์„์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํด๋ž˜์Šค ์ด๋ฆ„์— ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์•„์ง ์ •์˜๋˜์ง€ ์•Š์€ ํด๋ž˜์Šค ์ด๋ฆ„(์˜ˆ๋ฅผ ๋“ค์–ด, ํด๋ž˜์Šค ์„ ์–ธ ๋‚ด๋ถ€์—์„œ ํด๋ž˜์Šค ์ด๋ฆ„์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜ ์ฝ”๋“œ์—์„œ ๋‚˜์ค‘์— ์ •์˜๋œ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ)์„ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒฝ์šฐ, `from __future__ import annotations`๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํด๋ž˜์Šค ์ด๋ฆ„์„ ๋ฌธ์ž์—ด๋กœ ์‚ฌ์šฉํ•˜์„ธ์š”. -```python -from __future__ import annotations + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ -class MyClass: + ```python + from __future__ import annotations - def __init__(self, stack: Sequence[MyClass]) -> None: -``` + class MyClass: + def __init__(self, stack: Sequence[MyClass], item: OtherClass) -> None: + + class OtherClass: + ... + ``` + + ```python + class MyClass: + def __init__(self, stack: Sequence['MyClass'], item: 'OtherClass') -> None: + + class OtherClass: + ... + ``` #### 3.19.4 ๊ธฐ๋ณธ ๊ฐ’ - PEP-008์— ๋”ฐ๋ผ ์œ ํ˜• ์ฃผ์„๊ณผ ๊ธฐ๋ณธ๊ฐ’์ด ๋ชจ๋‘ ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฒฝ์šฐ "=" \_ only" ์ฃผ์œ„์— ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. -- [PEP-008](https://www.python.org/dev/peps/pep-0008/#other-recommendations)์— ๋”ฐ๋ผ Type ์ฃผ์„๊ณผ ๊ธฐ๋ณธ ๊ฐ’์ด ๋ชจ๋‘ ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฒฝ์šฐ `=` _only_ ์ฃผ์œ„์— ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์„ธ์š”, +- [PEP-008](https://peps.python.org/pep-0008/#other-recommendations)์— ๋”ฐ๋ผ Type ์ฃผ์„๊ณผ ๊ธฐ๋ณธ ๊ฐ’์ด ๋ชจ๋‘ ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฒฝ์šฐ `=` _only_ ์ฃผ์œ„์— ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์„ธ์š”, - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -2445,19 +2626,20 @@ class MyClass: #### 3.19.5 NoneType -- ํŒŒ์ด์ฌํ˜•์—์„œ ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ํผ์ŠคํŠธํด๋ž˜์Šคํ˜•์ด๋ฉฐ, ํƒ€์ดํ•‘์„ ์œ„ํ•ด ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ๋…ธ๋„คํƒ€์ž…(NoneType)์˜ ๋ณ„์นญ์ด๋‹ค. ๋…ผ์Ÿ์ด '์—†์Œ'์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค! ์œ ๋‹ˆ์˜จ(Union)์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋‹ค๋ฅธ ์œ ํ˜•์ด ํ•˜๋‚˜๋งŒ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” ์„ ํƒ์‚ฌํ•ญ(Option)์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. - -- ํŒŒ์ด์ฌ ํƒ€์ž… ์‹œ์Šคํ…œ์—์„œ `NoneType`์€ "first class" Type ์ด๋ฉฐ ์ž‘์„ฑ์„ ์œ„ํ•ด `None`์€ `NoneType`์˜ alias(๋ณ„์นญ)์ž…๋‹ˆ๋‹ค. ์ธ์ž๋Š” `None`์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์„ ์–ธ์„ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค! `Union`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‹ค๋ฅธ Type์ด ํ•˜๋‚˜๋งŒ ์žˆ๋Š” ๊ฒฝ์šฐ `Optional`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ํŒŒ์ด์ฌํ˜•์—์„œ ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ํผ์ŠคํŠธํด๋ž˜์Šคํ˜•์ด๋ฉฐ, ํƒ€์ดํ•‘์„ ์œ„ํ•ด ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ๋…ธ๋„คํƒ€์ž…(NoneType)์˜ ๋ณ„์นญ์ด๋‹ค. +- ์ธ์ž๊ฐ€ `None`์ด ๋  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ, ์ด๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค! +- ์ƒˆ๋กœ์šด Python 3.10+ ์ฝ”๋“œ์—์„œ๋Š” `|` ์œ ๋‹ˆ์˜จ ํƒ€์ž… ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋˜๋ฉฐ, ์ด์ „์—๋Š” `Optional`๊ณผ `Union` ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -- ์•”์‹œ์  `Optional` ๋Œ€์‹  ๋ช…์‹œ์  `Optional` ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. PEP 484 ์ด์ „ ๋ฒ„์ „์—์„œ๋Š” `a: Optional[str] = None` ๋Œ€์‹ ์— `a: str = None` ๋ฅผ ์„ ํ˜ธํ–ˆ์ง€๋งŒ ์ง€๊ธˆ์€ ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- ์•”์‹œ์ ์ธ ๋Œ€์‹  ๋ช…์‹œ์ ์ธ `X | None`์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์ด์ „ ๋ฒ„์ „์˜ PEP 484์—์„œ๋Š” `a: str = None`์„ `a: str | None = None`์œผ๋กœ ํ•ด์„ํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ, ์ด์ œ๋Š” ์ด๊ฒƒ์ด ์„ ํ˜ธ๋˜๋Š” ๋™์ž‘์ด ์•„๋‹™๋‹ˆ๋‹ค. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - def func(a: Optional[str], b: Optional[str] = None) -> str: - ... - def multiple_nullable_union(a: Union[None, str, int]) -> str: - ... + def modern_or_union(a: str | int | None, b: str | None = None) -> str: + ... + def union_optional(a: Union[str, int, None], b: Optional[str] = None) -> str: + ... ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ @@ -2478,14 +2660,13 @@ class MyClass: - ์–ด๋ ค์šด Type์„ ๋ณ„์นญ์œผ๋กœ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณ„์นญ์€ CapWorded์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ณ„์นญ์ด ์ด ๋ชจ๋“ˆ์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” \_Private์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์˜ˆ๋ฅผ ๋“ค์–ด Type๊ณผ ํ•จ๊ป˜ ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์ด ๋„ˆ๋ฌด ๊ธด ๊ฒฝ์šฐ +- TypeAlias ์ฃผ์„์€ ๋ฒ„์ „ 3.10 ์ด์ƒ์—์„œ๋งŒ ์ง€์›๋œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. - ```python - _ShortName = module_with_long_name.TypeWithLongName - ComplexMap = Mapping[str, List[Tuple[int, int]]] - ``` - -- ๋‹ค๋ฅธ ์˜ˆ๋กœ๋Š” ๋ณต์žกํ•œ ์ค‘์ฒฉ ์œ ํ˜•๊ณผ ํ•จ์ˆ˜์˜ ๋ณต์ˆ˜ ๋ฐ˜ํ™˜ ๋ณ€์ˆ˜(ํŠœํ”Œ)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. +```python +from typing import TypeAlias +_LossAndGradient: TypeAlias = tuple[tf.Tensor, tf.Tensor] +ComplexTFMap: TypeAlias = Mapping[str, _LossAndGradient] +``` @@ -2505,11 +2686,21 @@ class MyClass: #### 3.19.8 ๋‚ด๋ถ€ ๋ณ€์ˆ˜ ์ž‘์„ฑ -- ๋‚ด๋ถ€ ๋ณ€์ˆ˜๊ฐ€ ์œ ์ถ”ํ•˜๊ธฐ ์–ด๋ ต๊ฑฐ๋‚˜ ๋ถˆ๊ฐ€๋Šฅํ•œ ํƒ€์ž…์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ„๋„์˜ ์ฃผ์„์œผ๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + -```python -a = SomeUndecoratedFunction() # type: Foo -``` +- [_Annotated Assignments_](#annotated-assignments): ๋‚ด๋ถ€ ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์ถ”๋ก ํ•˜๊ธฐ ์–ด๋ ต๊ฑฐ๋‚˜ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ, ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ํ• ๋‹น์œผ๋กœ ํƒ€์ž…์„ ๋ช…์‹œํ•˜์„ธ์š”. ๋ณ€์ˆ˜ ์ด๋ฆ„๊ณผ ๊ฐ’ ์‚ฌ์ด์— ์ฝœ๋ก ๊ณผ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค (๊ธฐ๋ณธ๊ฐ’์ด ์žˆ๋Š” ํ•จ์ˆ˜ ์ธ์ˆ˜์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ). + + ```python + a: Foo = SomeUndecoratedFunction() + ``` + + + +- [_Type Comments_](#type-comments): ์ฝ”๋“œ๋ฒ ์ด์Šค์— ์—ฌ์ „ํžˆ ๋‚จ์•„ ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ (Python 3.6 ์ด์ „์—๋Š” ํ•„์š”ํ–ˆ์Œ), ๋” ์ด์ƒ `# type: ` ์ฃผ์„์„ ์ค„ ๋์— ์ถ”๊ฐ€ํ•˜์ง€ ๋งˆ์„ธ์š”. + + ```python + a = SomeUndecoratedFunction() # type: Foo + ``` @@ -2521,30 +2712,38 @@ a = SomeUndecoratedFunction() # type: Foo - ๋ฆฌ์ŠคํŠธ๋Š” ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. ```python -a = [1, 2, 3] # type: List[int] -b = (1, 2, 3) # type: Tuple[int, ...] -c = (1, "2", 3.5) # type: Tuple[int, str, float] +a: list[int] = [1, 2, 3] +b: tuple[int, ...] = (1, 2, 3) +c: tuple[int, str, float] = (1, "2", 3.5) ``` + -#### 3.19.10 TypeVar +#### 3.19.10 Type variables - ํŒŒ์ด์ฌํ˜• ์‹œ์Šคํ…œ์€ ์ผ๋ฐ˜์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ณต์žฅ ๊ธฐ๋Šฅ์ธ TypeVar๋Š” ํ”ํžˆ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. -- ํŒŒ์ด์„  Type์—๋Š” [generics](https://www.python.org/dev/peps/pep-0484/#generics)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. -- factory function `TypeVar`๋Š” ํ”ํžˆ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. +- ํŒŒ์ด์„  Type์—๋Š” [generics](https://peps.python.org/pep-0484/#generics)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. +- `TypeVar`์™€ `ParamSpec`๊ณผ ๊ฐ™์€ ํƒ€์ž… ๋ณ€์ˆ˜๋Š” ์ œ๋„ˆ๋ฆญ์„ ์‚ฌ์šฉํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ```python - from typing import List, TypeVar - T = TypeVar("T") + from collections.abc import Callable + from typing import ParamSpec, TypeVar + _P = ParamSpec("_P") + _T = TypeVar("_T") ... - def next(l: List[T]) -> T: - return l.pop() + def next(l: list[_T]) -> _T: + return l.pop() + def print_when_called(f: Callable[_P, _T]) -> Callable[_P, _T]: + def inner(*args: _P.args, **kwargs: _P.kwargs) -> _T: + print("Function was called") + return f(*args, **kwargs) + return inner ``` -- TypeVar๋Š” ๋ถ€์ž์—ฐ์Šค๋Ÿฌ์šธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +- `TypeVar`๋Š” ๋ถ€์ž์—ฐ์Šค๋Ÿฌ์šธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ```python AddableType = TypeVar("AddableType", int, float, str) @@ -2552,7 +2751,7 @@ c = (1, "2", 3.5) # type: Tuple[int, str, float] return a + b ``` -- `typing` ๋ชจ๋“ˆ์˜ ํ”ํžˆ ๋ฏธ๋ฆฌ ์ •์˜๋œ Type ๋ณ€์ˆ˜๋Š” `AnyStr`์ž…๋‹ˆ๋‹ค. `bytes`, `unicode`์ผ ์ˆ˜ ์žˆ๊ณ  ๋ชจ๋‘ ๊ฐ™์€ Type์ด์–ด์•ผ ํ•˜๋Š” ์—ฌ๋Ÿฌ ์ฃผ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +- `typing` ๋ชจ๋“ˆ์˜ ํ”ํžˆ ๋ฏธ๋ฆฌ ์ •์˜๋œ Type ๋ณ€์ˆ˜๋Š” `AnyStr`์ž…๋‹ˆ๋‹ค. `bytes`, `str`์ผ ์ˆ˜ ์žˆ๊ณ  ๋ชจ๋‘ ๊ฐ™์€ Type์ด์–ด์•ผ ํ•˜๋Š” ์—ฌ๋Ÿฌ ์ฃผ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ```python from typing import AnyStr @@ -2562,48 +2761,46 @@ c = (1, "2", 3.5) # type: Tuple[int, str, float] raise ValueError() ``` - - +- ํƒ€์ž… ๋ณ€์ˆ˜๋Š” ์„ค๋ช…์ ์ธ ์ด๋ฆ„์„ ๊ฐ€์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ, ๋‹ค์Œ ๋ชจ๋“  ๊ธฐ์ค€์„ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์˜ˆ์™ธ์ž…๋‹ˆ๋‹ค. -#### 3.19.11 ๋ฌธ์ž์—ด Type + - ์™ธ๋ถ€์—์„œ ๋ณด์ด์ง€ ์•Š๋Š” ๊ฒฝ์šฐ + - ์ œ์•ฝ ์กฐ๊ฑด์ด ์—†๋Š” ๊ฒฝ์šฐ -- String ์ฃผ์„์— ๋Œ€ํ•œ ์ ์ ˆํ•œ Type์€ ์ฝ”๋“œ์˜ ์šฉ๋„์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ + + ```python + _T = TypeVar("_T") + _P = ParamSpec("_P") + AddableType = TypeVar("AddableType", int, float, str) + AnyFunction = TypeVar("AnyFunction", bound=Callable) + ``` -- `str`์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜์ง€๋งŒ `Text`๋„ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ `bytes`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ(Python 2์—์„œ๋Š” `str` ๋˜๋Š” `unicode`, Python3์—์„œ๋Š” `str`)๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” Python 2 ํ˜ธํ™˜ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ `Text`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ -```python -def deals_with_text_data_in_py3(x: str) -> str: - ... -def deals_with_binary_data(x: bytes) -> bytes: - ... -def py2_compatible_text_data_processor(x: Text) -> Text: - ... -``` + ```python + T = TypeVar("T") + P = ParamSpec("P") + _T = TypeVar("_T", int, float, str) + _F = TypeVar("_F", bound=Callable) + ``` -- ์ผ๋ถ€ ํ”ํ•˜์ง€ ์•Š์€ Python2 ํ˜ธํ™˜์„ฑ ์‚ฌ๋ก€์—์„œ๋Š” `Text` ๋Œ€์‹  `str`์ด ์˜๋ฏธ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ Python2์™€ Python3 ๊ฐ„์— ๋ฐ˜ํ™˜ ์œ ํ˜•์ด ๋™์ผํ•˜์ง€ ์•Š์„ ๋•Œ ํ˜ธํ™˜์„ฑ์„ ๋•๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. -- Python3์—๋Š” `unicode`๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ ˆ๋Œ€ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. -- ์ด๋Ÿฌํ•œ ๋ถˆ์ผ์น˜๊ฐ€ ์กด์žฌํ•˜๋Š” ์ด์œ ๋Š” `str`์ด Python3์™€ Python2์—์„œ ๋‹ค๋ฅธ ์˜๋ฏธ๋ฅผ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + + + + -- ๋ถ€์ ์ ˆํ•œ ์˜ˆ +#### 3.19.11 ๋ฌธ์ž์—ด Type -```python -def py2_code(x: str) -> unicode: - ... -``` +> ์ƒˆ๋กœ์šด ์ฝ”๋“œ์—์„œ๋Š” `typing.Text`๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. ์ด๋Š” Python 2/3 ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. -If the type can be either bytes or text, use `Union`, with the appropriate text -type. +- ๋ฌธ์ž์—ด/ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์—๋Š” `str`์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ด์ง„ ๋ฐ์ดํ„ฐ์™€ ๊ด€๋ จ๋œ ์ฝ”๋“œ์—์„œ๋Š” `bytes`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -```python -from typing import Text, Union -... -def py3_only(x: Union[bytes, str]) -> Union[bytes, str]: - ... -def py2_compatible(x: Union[bytes, Text]) -> Union[bytes, Text]: - ... -``` + ```python + def deals_with_text_data(x: str) -> str: + ... + def deals_with_binary_data(x: bytes) -> bytes: + ... + ``` - ํ•จ์ˆ˜์˜ ๋ชจ๋“  string Type์ด ํ•ญ์ƒ ๋™์ผํ•œ ๊ฒฝ์šฐ(์˜ˆ, ๋ฐ˜ํ™˜ Type์ด ์œ„์˜ ์ฝ”๋“œ์—์„œ ์ธ์ž Type๊ณผ ๋™์ผํ•œ ๊ฒฝ์šฐ) [AnyStr](#s3.19.10-type-var)๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -2614,19 +2811,31 @@ def py2_compatible(x: Union[bytes, Text]) -> Union[bytes, Text]: #### 3.19.12 Typing ์ถ”๊ฐ€ -- `typing` ๋ชจ๋“ˆ์˜ ํด๋ž˜์Šค๋Š” ํ•ญ์ƒ ํด๋ž˜์Šค ์ž์ฒด๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. `typing` ๋ชจ๋“ˆ์—์„œ ํ•œ ์ค„์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ํŠน์ • ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- `typing` ๋˜๋Š” `collections.abc` ๋ชจ๋“ˆ์—์„œ ์ •์  ๋ถ„์„ ๋ฐ ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ์‹ฌ๋ณผ(ํƒ€์ž…, ํ•จ์ˆ˜, ์ƒ์ˆ˜ ๋“ฑ)์€ ํ•ญ์ƒ ์‹ฌ๋ณผ ์ž์ฒด๋ฅผ ์ž„ํฌํŠธํ•˜์„ธ์š”. +- ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ผ๋ฐ˜์ ์ธ ์ฃผ์„์ด ๋” ๊ฐ„๊ฒฐํ•ด์ง€๊ณ , ์ „ ์„ธ๊ณ„์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํƒ€์ž… ์ฃผ์„ ๊ด€ํ–‰์— ๋งž์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- `typing` ๋ฐ `collections.abc` ๋ชจ๋“ˆ์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŠน์ • ์‹ฌ๋ณผ์„ ํ•œ ์ค„์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ž„ํฌํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python - from typing import Any, Dict, Optional + from collections.abc import Mapping, Sequence + from typing import Any, Generic, cast, TYPE_CHECKING ``` -- `typing`์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์ด ๋กœ์ปฌ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•œ๋‹ค๋Š” ์ ์—์„œ, `typing`์˜ ๋ชจ๋“  ์ด๋ฆ„์€ ํ‚ค์›Œ๋“œ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ทจ๊ธ‰๋˜์–ด์•ผ ํ•˜๋ฉฐ, typing์ด๋“  ์•„๋‹ˆ๋“  Python ์ฝ”๋“œ์— ์ •์˜๋˜์–ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค. -- ๋ชจ๋“ˆ์— ์žˆ๋Š” Type๊ณผ ๊ธฐ์กด ์ด๋ฆ„์ด ์ถฉ๋Œํ•˜๋Š” ๊ฒฝ์šฐ `import x as y`๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์ด ๋ฐฉ์‹์œผ๋กœ ์ž„ํฌํŠธํ•˜๋ฉด ๋กœ์ปฌ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ํ•ญ๋ชฉ์ด ์ถ”๊ฐ€๋˜๋ฏ€๋กœ, `typing` ๋˜๋Š” `collections.abc`์˜ ์ด๋ฆ„์€ ํ‚ค์›Œ๋“œ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ทจ๊ธ‰๋˜์–ด์•ผ ํ•˜๋ฉฐ, Python ์ฝ”๋“œ์—์„œ ์ •์˜๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์ž… ์—ฌ๋ถ€์™€ ๊ด€๊ณ„์—†์ด ๋ง์ž…๋‹ˆ๋‹ค. +- ๋ชจ๋“ˆ ๋‚ด์—์„œ ํƒ€์ž…๊ณผ ๊ธฐ์กด ์ด๋ฆ„ ๊ฐ„์— ์ถฉ๋Œ์ด ์žˆ๋Š” ๊ฒฝ์šฐ, `import x as y`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž„ํฌํŠธํ•˜์„ธ์š”. ```python from typing import Any as AnyType ``` +- ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ, ์ฃผ์„์œผ๋กœ ๋‚ด์žฅ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. +- Prefer to use built-in types as annotations where available. +- Python์€ [PEP-585](https://peps.python.org/pep-0585/)๋ฅผ ํ†ตํ•ด ๋งค๊ฐœํ˜• ์ปจํ…Œ์ด๋„ˆ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ ํƒ€์ž… ์ฃผ์„์„ ์ง€์›ํ•˜๋ฉฐ, ์ด๋Š” Python 3.9์—์„œ ๋„์ž…๋˜์—ˆ์Šต๋‹ˆ๋‹ค. + + ```python + def generate_foo_scores(foo: set[str]) -> list[float]: + ... + ``` + @@ -2667,7 +2876,7 @@ def f(x: "sketch.Sketch"): ... - ํ•˜์ง€๋งŒ ๊ธฐ์ˆ ์ ์œผ๋กœ Circular ์ข…์†์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๋‹ค์–‘ํ•œ ๋นŒ๋“œ ์‹œ์Šคํ…œ์€ ๋‹ค๋ฅธ ๋ชจ๋“ˆ์— ์˜์กดํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ ‡๊ฒŒ ํ•˜๋„๋ก ํ—ˆ๋ฝํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. - Circular ์ข…์†์„ ์ƒ์„ฑํ•˜๋Š” ๋ชจ๋“ˆ์„ `Any`๋กœ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค. - - ์˜๋ฏธ์žˆ๋Š” ์ด๋ฆ„์œผ๋กœ [alias](#s3.19.6-aliases)๋ฅผ ์ง€์ •ํ•˜๊ณ  ๋ชจ๋“ˆ์˜ ์‹ค์ œ Type ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์„ธ์š” (์–ด๋–ค ๊ฒƒ์˜ ์–ด๋–ค ์†์„ฑ์ธ Any). + - ์˜๋ฏธ์žˆ๋Š” ์ด๋ฆ„์œผ๋กœ [alias](#s3.19.6-aliases)๋ฅผ ์ง€์ •ํ•˜๊ณ  ๋ชจ๋“ˆ์˜ ์‹ค์ œ Type ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์„ธ์š” (`Any`์˜ ๋ชจ๋“  ์†์„ฑ์€ `Any`์ž…๋‹ˆ๋‹ค.). - Alias์˜ ์ •์˜๋Š” ๋งˆ์ง€๋ง‰์œผ๋กœ import์™€ ํ•œ ์ค„๋กœ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ```python @@ -2684,34 +2893,38 @@ def my_method(self, var: "some_mod.SomeType") -> None: #### 3.19.15 ์ผ๋ฐ˜ -- ์ฃผ์„์„ ๋‹ฌ๋•Œ, ์ผ๋ฐ˜ Type๋ฅผ ์ง€์ •ํ•˜๊ธฐ๋ฅผ ์„ ํ˜ธํ•˜๋ฉฐ ๊ทธ๋ ‡์ง€ [์•Š์„ ๋•Œ์—๋Š” `Any`๋กœ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค](https://www.python.org/dev/peps/pep-0484/#the-any-type). +- ์ฃผ์„์„ ๋‹ฌ๋•Œ, ์ผ๋ฐ˜ Type๋ฅผ ์ง€์ •ํ•˜๊ธฐ๋ฅผ ์„ ํ˜ธํ•˜๋ฉฐ ๊ทธ๋ ‡์ง€ [์•Š์„ ๋•Œ์—๋Š” `Any`๋กœ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค](https://peps.python.org/pep-0484/#the-any-type). -```python -def get_names(employee_ids: List[int]) -> Dict[int, Any]: - ... -``` + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ -```python -# ๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜ ๋ชจ๋‘ get_names(employee_ids: List[Any]) -> Dict[Any, Any] -def get_names(employee_ids: list) -> Dict: - ... + ```python + def get_names(employee_ids: Sequence[int]) -> Mapping[int, str]: + ... + ``` -def get_names(employee_ids: List) -> Dict: - ... -``` + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ + + ```python + # ์ด๋Š” get_names(employee_ids: Sequence[Any]) -> Mapping[Any, Any]๋กœ ํ•ด์„๋ฉ๋‹ˆ๋‹ค. + def get_names(employee_ids: Sequence) -> Mapping: + ``` - ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ ํ•ฉํ•œ Type์ด `Any`์ผ ๋•Œ, ๋ช…์‹œ์ ์œผ๋กœ ํ‘œํ˜„๋˜๋ฉฐ, ๋งŽ์€ ๊ฒฝ์šฐ์— [`TypeVar`](#s3.19.10-type-var)๊ฐ€ ๋” ์ ํ•ฉํ•  ์ˆ˜ ์žˆ์Œ์„ ๊ธฐ์–ตํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. -```python -def get_names(employee_ids: List[Any]) -> Dict[Any, str]: - """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" -``` + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ -```python -T = TypeVar('T') -def get_names(employee_ids: List[T]) -> Dict[T, str]: - """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" -``` + ```python + def get_names(employee_ids: Sequence[Any]) -> Mapping[Any, str]: + """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" + ``` + + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ + + ```python + _T = TypeVar('_T') + def get_names(employee_ids: Sequence[_T]) -> Mapping[_T, str]: + """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" + ``` --- @@ -2724,9 +2937,14 @@ def get_names(employee_ids: List[T]) -> Dict[T, str]:

์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜์„ธ์š”

- ๋‹น์‹ ์ด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค๋ฉด ๋ช‡ ๋ถ„์„ ํˆฌ์žํ•ด์„œ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ณ  ์Šคํƒ€์ผ์„ ํŒŒ์•…ํ•˜์„ธ์š”. -- ๋งŒ์•ฝ ๋ชจ๋“  ์‚ฐ์ˆ  ์—ฐ์‚ฐ์ž์— ๊ณต๋ฐฑ์„ ๋„ฃ์—ˆ๋‹ค๋ฉด ๋‹น์‹ ๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ฃผ์„์ด hash marks(`#`)์œผ๋กœ ๋งŒ๋“  ๋ฐ•์Šค ์•ˆ์— ๋“ค์–ด์žˆ๋‹ค๋ฉด ๋‹น์‹ ์˜ ์ฃผ์„๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. +- ๊ทธ๋“ค์ด ์ธ๋ฑ์Šค ๋ณ€์ˆ˜ ์ด๋ฆ„์— `_idx` ์ ‘๋ฏธ์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ๋‹น์‹ ๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ฃผ์„์ด hash marks(`#`)์œผ๋กœ ๋งŒ๋“  ๋ฐ•์Šค ์•ˆ์— ๋“ค์–ด์žˆ๋‹ค๋ฉด ๋‹น์‹ ์˜ ์ฃผ์„๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. + - ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ๋ผ์ธ์˜ ์š”์ ์€ ์ฝ”๋”ฉ์—์„œ ๊ณตํ†ต๋œ ์–ดํˆฌ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋œ๋‹ค๋ฉด ์‚ฌ๋žŒ๋“ค์€ ๋‹น์‹ ์˜ ์ฝ”๋”ฉ ํ˜•์‹๋ณด๋‹ค๋Š” ๋‹น์‹ ์˜ ์ฝ”๋“œ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค - ์šฐ๋ฆฌ๋Š” ์—ฌ๊ธฐ์„œ ์‚ฌ๋žŒ๋“ค์ด ์–ดํœ˜๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋Š” ์„ธ๊ณ„์ ์ธ ์ฝ”๋”ฉ ์Šคํƒ€์ผ ๊ทœ์น™์„ ์ œ๊ณตํ•˜์ง€๋งŒ ๊ณ ์œ ์˜ ์Šคํƒ€์ผ๋„ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. -- ํŒŒ์ผ์— ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์„ ๋•Œ ์ด ์ฝ”๋“œ๊ฐ€ ๋‹ค๋ฅธ ์ฝ”๋“œ์™€ ๋น„๊ตํ•˜์—ฌ ํฌ๊ฒŒ ๋‹ฌ๋ผ ๋ณด์ด๋ฉด ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ์‚ฌ๋žŒ์˜ ์ž…์žฅ์—์„œ๋Š” ๋ฆฌ๋“ฌ์ด ๊นจ์ง‘๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์„ ์ฃผ์˜ํ•˜์„ธ์š”. +- ํŒŒ์ผ์— ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์„ ๋•Œ ์ด ์ฝ”๋“œ๊ฐ€ ๋‹ค๋ฅธ ์ฝ”๋“œ์™€ ๋น„๊ตํ•˜์—ฌ ํฌ๊ฒŒ ๋‹ฌ๋ผ ๋ณด์ด๋ฉด ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ์‚ฌ๋žŒ์˜ ์ž…์žฅ์—์„œ๋Š” ๋ฆฌ๋“ฌ์ด ๊นจ์ง‘๋‹ˆ๋‹ค. + +- ๊ทธ๋Ÿฌ๋‚˜ ์ผ๊ด€์„ฑ์—๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. +- ์ผ๊ด€์„ฑ์€ ์ฃผ๋กœ ์ง€์—ญ์ ์œผ๋กœ ์ ์šฉ๋˜๋ฉฐ, ์ „์—ญ ์Šคํƒ€์ผ์—์„œ ๋ช…์‹œ๋˜์ง€ ์•Š์€ ์„ ํƒ์— ๋” ๊ฐ•ํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. +- ์ผ๊ด€์„ฑ์„ ๊ตฌ์‹ ์Šคํƒ€์ผ์„ ๊ณ ์ˆ˜ํ•˜๋Š” ์ •๋‹นํ™”์˜ ๊ทผ๊ฑฐ๋กœ ์‚ผ๊ธฐ๋ณด๋‹ค๋Š” ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ์˜ ์žฅ์ ์ด๋‚˜ ์ฝ”๋“œ๋ฒ ์ด์Šค๊ฐ€ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ๋กœ ์ˆ˜๋ ดํ•˜๋Š” ๊ฒฝํ–ฅ์„ ๊ณ ๋ คํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. --- diff --git "a/Google Python Style Guide/1. \353\260\260\352\262\275/1.1 \353\260\260\352\262\275.md" "b/Google Python Style Guide/1. \353\260\260\352\262\275/1.1 \353\260\260\352\262\275.md" index 3d1bb9c..b8a52b9 100644 --- "a/Google Python Style Guide/1. \353\260\260\352\262\275/1.1 \353\260\260\352\262\275.md" +++ "b/Google Python Style Guide/1. \353\260\260\352\262\275/1.1 \353\260\260\352\262\275.md" @@ -2,4 +2,4 @@ - ์ด ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ๋Š” Python ํ”„๋กœ๊ทธ๋žจ์—์„œ _ํ•ด์•ผ ํ•  ๊ฒƒ๋“ค๊ณผ ํ•˜์ง€ ๋ง์•„์•ผ ํ•  ๊ฒƒ_ ๋“ค์„ ์ ์–ด๋†“์•˜์Šต๋‹ˆ๋‹ค. - ์ฝ”๋“œ ํ˜•์‹์„ ์ •ํ™•ํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ๋“ค ๋•๊ธฐ ์œ„ํ•ด, ์šฐ๋ฆฌ๋Š” [settings file for Vim](google_python_style.vim)์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. - Emacs ํŽธ์ง‘๊ธฐ์—์„œ๋Š” ๊ธฐ๋ณธ ์„ค์ •๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. -- ๋งŽ์€ ํŒ€์—์„œ ํ˜•์‹์— ๋Œ€ํ•œ ๋…ผ์Ÿ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด [yapf](https://github.com/google/yapf/) auto-formatter ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +- ๋งŽ์€ ํŒ€์—์„œ ํ˜•์‹์— ๋Œ€ํ•œ ๋…ผ์Ÿ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด [Black](https://github.com/psf/black) ํ˜น์€ [Pyink](https://github.com/google/pyink) auto-formatter ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. diff --git "a/Google Python Style Guide/1. \353\260\260\352\262\275/ReadMe.md" "b/Google Python Style Guide/1. \353\260\260\352\262\275/ReadMe.md" index 95a60bc..6e36234 100644 --- "a/Google Python Style Guide/1. \353\260\260\352\262\275/ReadMe.md" +++ "b/Google Python Style Guide/1. \353\260\260\352\262\275/ReadMe.md" @@ -2,6 +2,6 @@ - ์ด ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ๋Š” Python ํ”„๋กœ๊ทธ๋žจ์—์„œ _ํ•ด์•ผ ํ•  ๊ฒƒ๋“ค๊ณผ ํ•˜์ง€ ๋ง์•„์•ผ ํ•  ๊ฒƒ_ ๋“ค์„ ์ ์–ด๋†“์•˜์Šต๋‹ˆ๋‹ค. - ์ฝ”๋“œ ํ˜•์‹์„ ์ •ํ™•ํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ๋“ค ๋•๊ธฐ ์œ„ํ•ด, ์šฐ๋ฆฌ๋Š” [settings file for Vim](google_python_style.vim)์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. - Emacs ํŽธ์ง‘๊ธฐ์—์„œ๋Š” ๊ธฐ๋ณธ ์„ค์ •๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. -- ๋งŽ์€ ํŒ€์—์„œ ํ˜•์‹์— ๋Œ€ํ•œ ๋…ผ์Ÿ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด [yapf](https://github.com/google/yapf/) auto-formatter ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +- ๋งŽ์€ ํŒ€์—์„œ ํ˜•์‹์— ๋Œ€ํ•œ ๋…ผ์Ÿ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด [Black](https://github.com/psf/black) ํ˜น์€ [Pyink](https://github.com/google/pyink) auto-formatter ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. --- diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.1 Lint.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.1 Lint.md" index bb18076..13bc698 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.1 Lint.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.1 Lint.md" @@ -38,7 +38,8 @@ - ๊ฒฝ๊ณ ๋ฅผ ๋„์šฐ์ง€ ์•Š๊ธฐ ์œ„ํ•ด, ์ฝ”๋“œ์— ๋ผ์ธ ๋‹จ์œ„๋กœ ์ฃผ์„์„ ๋‹ฌ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ```python - dict = 'something awful' # Bad Idea... pylint: disable=redefined-builtin + def do_PUT(self): # WSGI name, so pylint: disable=invalid-name + ... ``` - `pylint`์˜ ๊ฒฝ๊ณ ๋Š” ๊ฐ๊ฐ symbolic name(`empty-docstring`)์œผ๋กœ ๊ตฌ๋ณ„๋ฉ๋‹ˆ๋‹ค. @@ -54,7 +55,7 @@ - ๊ฐ ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•ด ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ์–ป๊ณ ์ž ํ•˜๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```shell - pylint --help-msg=C6409 + pylint --help-msg=invalid-name ``` - `pyling: disable-msg`๋Š” ์ด์ „์— ์‚ฌ์šฉํ–ˆ๋˜ ๋ฐฉ์‹์œผ๋กœ ์ด์ œ๋Š” ์‚ฌ์šฉ๋˜์ง€ ์•Š์œผ๋ฉฐ `pylint: disable`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. @@ -62,7 +63,7 @@ - ์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. ```python - def viking_cafe_order(spam: str, beans: str, eggs: Optional[str] = None) -> str: + def viking_cafe_order(spam: str, beans: str, eggs: str | None = None) -> str: del beans, eggs # Unused by vikings. return spam + spam + spam ``` diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.10 \353\236\214\353\213\244.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.10 \353\236\214\353\213\244.md" index 1dd955c..49be062 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.10 \353\236\214\353\213\244.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.10 \353\236\214\353\213\244.md" @@ -28,8 +28,6 @@ #### 2.10.4 ๊ฒฐ๋ก  -- ๋žŒ๋‹ค๋ฅผ ํ•œ ์ค„๋กœ ์‚ฌ์šฉํ•˜์„ธ์š”. ๋งŒ์•ฝ ์ฝ”๋“œ ๋‚ด๋ถ€์— ์žˆ๋Š” ๋žŒ๋‹ค ํ•จ์ˆ˜๊ฐ€ 60~80๊ธ€์ž ์ˆ˜ ์ •๋„๋กœ ๊ธธ๋‹ค๋ฉด ๊ทธ๊ฑด ์•„๋งˆ ๋” ์ผ๋ฐ˜์ ์ธ - [Lexical Scoping(๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ•‘)](#s2.16-lexical-scoping)์œผ๋กœ ์ •์˜ํ•˜๋Š”๊ฒŒ ๋‚˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. - +- ๋žŒ๋‹ค ํ•จ์ˆ˜๋Š” ํ—ˆ์šฉํ•˜์ง€๋งŒ, ๋žŒ๋‹ค ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์ฝ”๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ์ค„์— ๊ฑธ์น˜๊ฑฐ๋‚˜ 60-80์ž๋ฅผ ๋„˜๋Š” ๊ฒฝ์šฐ, ์ผ๋ฐ˜์ ์ธ [์ค‘์ฒฉ ํ•จ์ˆ˜](#s2.16-lexical-scoping)๋กœ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - ๊ณฑ์…ˆ ๊ฐ™์€ ์ผ๋ฐ˜ ์—ฐ์‚ฐ์ž์—์„œ๋Š” `operator`๋ชจ๋“ˆ ๋Œ€์‹ ์— ๋žŒ๋‹ค ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. - ์˜ˆ๋ฅผ ๋“ค์–ด, `operator.mul`์„ `lambda x,y : x * y` ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.12 \352\270\260\353\263\270 \354\235\270\354\236\220 \352\260\222.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.12 \352\270\260\353\263\270 \354\235\270\354\236\220 \352\260\222.md" index cd25666..9241081 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.12 \352\270\260\353\263\270 \354\235\270\354\236\220 \352\260\222.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.12 \352\270\260\353\263\270 \354\235\270\354\236\220 \352\260\222.md" @@ -50,7 +50,7 @@ def foo(a, b=None): if b is None: b = [] - def foo(a, b: Optional[Sequence] = None): + def foo(a, b: Sequence | None = None): if b is None: b = [] def foo(a, b: Sequence = ()): # tuples์€ ๋ถˆ๋ณ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. @@ -60,12 +60,15 @@ - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python + from absl import flags + _FOO = flags.DEFINE_string(...) + def foo(a, b=[]): ... - def foo(a, b=time.time()): # ๋ชจ๋“ˆ์ด ๋กœ๋“œ๊ฐ€ ๋  ๋•Œ์˜ ์‹œ๊ฐ„์ธ๊ฐ€??? + def foo(a, b=time.time()): # `b`๊ฐ€ ์ด ๋ชจ๋“ˆ์ด ๋กœ๋“œ๋œ ์‹œ๊ฐ„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ธ๊ฐ€์š”? ... - def foo(a, b=FLAGS.my_thing): # sys.argv๋Š” ์•„์ง ๊ตฌ๋ฌธ ๋ถ„์„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค... + def foo(a, b=_FOO.value): # sys.argv๋Š” ์•„์ง ๊ตฌ๋ฌธ ๋ถ„์„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค... ... - def foo(a, b: Mapping = {}): # ํ™•์ธ๋˜์ง€ ์•Š์€ ์ฝ”๋“œ๋กœ ์ „๋‹ฌ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค... + def foo(a, b: Mapping = {}): # ํ™•์ธ๋˜์ง€ ์•Š์€ ์ฝ”๋“œ๋กœ ์ „๋‹ฌ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ... ``` diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.14 True, False \355\217\211\352\260\200.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.14 True, False \355\217\211\352\260\200.md" index 6679926..dcbdbfc 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.14 True, False \355\217\211\352\260\200.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.14 True, False \355\217\211\352\260\200.md" @@ -2,7 +2,7 @@ ### 2.14 True/False ํ‰๊ฐ€ -- ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ "์•”๋ฌต์ (implicit)" `false`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ "์•”๋ฌต์ (implicit)" `false`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. (๋ช‡ ๊ฐ€์ง€ ์ฃผ์˜์‚ฌํ•ญ์ด ์žˆ์ง€๋งŒ) diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.16 \353\240\211\354\213\234\354\273\254 \354\212\244\354\275\224\355\225\221(Lexical Scoping).md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.16 \353\240\211\354\213\234\354\273\254 \354\212\244\354\275\224\355\225\221(Lexical Scoping).md" index d4be156..cc7b9b3 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.16 \353\240\211\354\213\234\354\273\254 \354\212\244\354\275\224\355\225\221(Lexical Scoping).md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.16 \353\240\211\354\213\234\354\273\254 \354\212\244\354\275\224\355\225\221(Lexical Scoping).md" @@ -33,7 +33,7 @@ #### 2.16.3 ๋‹จ์  -- ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๋ฒ„๊ทธ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. [PEP-0227](http://www.google.com/url?sa=D&q=http://www.python.org/dev/peps/pep-0227/)์—์„œ ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- [PEP-0227](https://peps.python.org/pep-0227)์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์ด ์˜ˆ์‹œ์™€ ๊ฐ™์ด ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๋ฒ„๊ทธ๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python i = 4 diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.17 \355\225\250\354\210\230\354\231\200 \353\251\224\354\204\234\353\223\234 Decorators.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.17 \355\225\250\354\210\230\354\231\200 \353\251\224\354\204\234\353\223\234 Decorators.md" index 1dd350f..1621f76 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.17 \355\225\250\354\210\230\354\231\200 \353\251\224\354\204\234\353\223\234 Decorators.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.17 \355\225\250\354\210\230\354\231\200 \353\251\224\354\204\234\353\223\234 Decorators.md" @@ -49,6 +49,6 @@ - Decorator๋Š” ๋ถ„๋ช…ํ•œ ์ด์ ์ด ์žˆ๋”๋ผ๋„ ํ˜„๋ช…ํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Decorator๋Š” import์™€ ๋ช…๋ช… ์ง€์นจ์„ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค. Decorator pydoc๋Š” decorator ํ•จ์ˆ˜ ์ž„์„ ๋ถ„๋ช…ํžˆ ๋ช…์‹œํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. dcorator๋ฅผ ์œ„ํ•œ ์œ ๋‹› ํ…Œ์ŠคํŠธ(unit test)๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. - Decorator(์˜ˆ. ํŒŒ์ผ, ์†Œ์ผ“, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋“ฑ) ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ (`pydoc` ํ˜น์€ ๊ธฐํƒ€ ๋„๊ตฌ๋ฅผ import ์‹œ๊ฐ„์— ๊ฐ€์ ธ์˜ฌ ๋•Œ) ์‚ฌ์šฉ ๋ชปํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ Decorator์˜ ์™ธ๋ถ€ ์˜์กด์„ฑ์„ ํ”ผํ•˜์„ธ์š”. ์œ ํšจํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง„ Decorator์€ ๋ชจ๋“  ๊ฒฝ์šฐ์— ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณด์žฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- Decorator๋Š” "Top level code"์˜ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์ผ ๋•Œ์—๋Š” [main](#s3.17-main) ํ•ญ๋ชฉ์— ์ž์„ธํ•œ ๋‚ด์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. +- Decorator๋Š” "Top-level code"์˜ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์ผ ๋•Œ์—๋Š” [main](#s3.17-main) ํ•ญ๋ชฉ์— ์ž์„ธํ•œ ๋‚ด์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. - ๊ธฐ์กด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ •์˜๋œ API์™€ ํ†ตํ•ฉํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ•์ œํ•˜์ง€ ์•Š๋Š” ํ•œ "staticmethod"๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. ๋Œ€์‹  ๋ชจ๋“ˆ ๋ ˆ๋ฒจ ํ•จ์ˆ˜๋ฅผ ์“ฐ์„ธ์š”. -- ํ”„๋กœ์„ธ์Šค ์ „์ฒด ์บ์‹œ ๋“ฑ ํ•„์š”ํ•œ global state๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋ช…๋ช…๋œ ์ƒ์„ฑ์ž ๋˜๋Š” ํด๋ž˜์Šค๋ณ„ ๋ฃจํ‹ด์„ ์ž‘์„ฑํ•  ๋•Œ๋งŒ "classmethod"๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- classmethod๋Š” ๋ช…๋ช…๋œ ์ƒ์„ฑ์ž๋ฅผ ์ž‘์„ฑํ•˜๊ฑฐ๋‚˜ ํ”„๋กœ์„ธ์Šค ์ „์ฒด ์บ์‹œ์™€ ๊ฐ™์€ ํ•„์ˆ˜ ์ „์—ญ ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ํด๋ž˜์Šค ํŠน์ • ๋ฃจํ‹ด์„ ์ž‘์„ฑํ•  ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”. diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.18 \354\212\244\353\240\210\353\223\234.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.18 \354\212\244\353\240\210\353\223\234.md" index cdaa505..e9f6d32 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.18 \354\212\244\353\240\210\353\223\234.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.18 \354\212\244\353\240\210\353\223\234.md" @@ -2,4 +2,4 @@ ### 2.18 ์Šค๋ ˆ๋“œ -- ๋‚ด์žฅ๋œ ํƒ€์ž…์˜ ์›์ž์„ฑ์— ์˜์กดํ•˜์ง€ ๋งˆ์„ธ์š”. ๋”•์…”๋„ˆ๋ฆฌ์™€ ๊ฐ™์€ Python์˜ ๋‚ด์žฅ๋œ ํƒ€์ž…์€ ์›์ž ํ˜•ํƒœ๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ๋Ÿฌ์ง€ ์•Š์€ ๊ฒฝ์šฐ(์˜ˆ: `__hash__`์ด๋‚˜ `__eq__`๊ฐ€ Python ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„๋˜๋Š” ๊ฒฝ์šฐ)๋„ ์žˆ์œผ๋ฉฐ ์›์ž๋กœ ๋˜์–ด์žˆ๋‹ค๊ณ  ์‹ ๋ขฐํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์›์ž ๋ณ€์ˆ˜ ํ• ๋‹น์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. (๊ฒฐ๊ตญ, ๋”•์…”๋„ˆ๋ฆฌ์— ๋‹ฌ๋ ค์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค) ์Šค๋ ˆ๋“œ ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ต์‹ ํ•˜๋Š” ๋ฐ ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํ ๋ชจ๋“ˆ์˜ `Queue` ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด threading ๋ชจ๋“ˆ์ด๋‚˜ locking primitives๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. lower-level lock ๋Œ€์‹ ํ•ด Condition variables์™€ `threading.Condition`๋ฅผ ์„ ํ˜ธํ•˜์„ธ์š”. +- ๋‚ด์žฅ๋œ ํƒ€์ž…์˜ ์›์ž์„ฑ์— ์˜์กดํ•˜์ง€ ๋งˆ์„ธ์š”. ๋”•์…”๋„ˆ๋ฆฌ์™€ ๊ฐ™์€ Python์˜ ๋‚ด์žฅ๋œ ํƒ€์ž…์€ ์›์ž ํ˜•ํƒœ๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ๋Ÿฌ์ง€ ์•Š์€ ๊ฒฝ์šฐ(์˜ˆ: `__hash__`์ด๋‚˜ `__eq__`๊ฐ€ Python ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„๋˜๋Š” ๊ฒฝ์šฐ)๋„ ์žˆ์œผ๋ฉฐ ์›์ž๋กœ ๋˜์–ด์žˆ๋‹ค๊ณ  ์‹ ๋ขฐํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์›์ž ๋ณ€์ˆ˜ ํ• ๋‹น์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. (๊ฒฐ๊ตญ, ๋”•์…”๋„ˆ๋ฆฌ์— ๋‹ฌ๋ ค์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค) ์Šค๋ ˆ๋“œ ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ต์‹ ํ•˜๋Š” ๋ฐ ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ `queue` ๋ชจ๋“ˆ์˜ `Queue` ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด `threading` ๋ชจ๋“ˆ์ด๋‚˜ locking primitives๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. lower-level lock ๋Œ€์‹ ํ•ด Condition variables์™€ `threading.Condition`๋ฅผ ์„ ํ˜ธํ•˜์„ธ์š”. diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.2 import.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.2 import.md" index 540bedb..ca138c7 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.2 import.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.2 import.md" @@ -2,7 +2,7 @@ ### 2.2 Imports -- `import`๋ฌธ์„ ์‚ฌ์šฉํ• ๋•Œ package์™€ module์— ์‚ฌ์šฉํ•˜๊ณ  ๊ฐœ๋ณ„ ํด๋ž˜์Šค๋‚˜ ํ•จ์ˆ˜์— ๋Œ€ํ•ด ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ [typing ๋ชจ๋“ˆ](#s3.19.12-imports), [typing_extensions module](https://github.com/python/typing/tree/master/typing_extensions)์—์„œ ๊ฐ€์ ธ์˜จ ํด๋ž˜์Šค ๋ฐ [six.moves module](https://six.readthedocs.io/#module-six.moves)์—์„œ์˜ ๋ฆฌ๋””๋ ‰์…˜์€ ์ด ๊ทœ์น™์—์„œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค. +- `import`๋ฌธ์€ ๊ฐœ๋ณ„ ํƒ€์ž…, ํด๋ž˜์Šค, ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ ํŒจํ‚ค์ง€์™€ ๋ชจ๋“ˆ์—๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”. (์ฃผ: ๊ฐœ๋ณ„ ํƒ€์ž…์€ ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•, ์‚ฌ์šฉ์ž ์ •์˜ ํด๋ž˜์Šค๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.) @@ -28,8 +28,13 @@ - `import x`๋ฅผ ํŒจํ‚ค์ง€์™€ ๋ชจ๋“ˆ์„ importํ• ๋•Œ ์‚ฌ์šฉํ•˜์„ธ์š”. - `from x import y`๋ฅผ `x`๊ฐ€ ํŒจํ‚ค์ง€์˜ ์ ‘๋‘์–ด์ด๊ณ  `y`๊ฐ€ ์ ‘๋‘์–ด๊ฐ€ ์—†๋Š” ๋ชจ๋“ˆ์ผ๋•Œ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ๋งŒ์•ฝ `y` ๋กœ ์ด๋ฆ„์ด ์ง€์–ด์ง„ ๋‘ ๋ชจ๋“ˆ์ด import๋˜๊ฑฐ๋‚˜ `y` ๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋„ˆ๋ฌด ๊ธด ์ด๋ฆ„์„ ๊ฐ€์กŒ๋‹ค๋ฉด `from x import y as z`๋ฅผ ์‚ฌ์šฉ์„ธ์š”. -- `import y as z`๋ฅผ `z` ๊ฐ€ ๊ณต์‹์ ์ธ ์•ฝ์–ด์ธ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”(e.g., `np` ๋Š” `numpy` ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.) +- ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ๋Š” `from x import y as z` ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + - `y`๋ผ๋Š” ์ด๋ฆ„์„ ๊ฐ€์ง„ ๋‘ ๊ฐœ์˜ ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. + - `y`๋Š” ํ˜„์žฌ ๋ชจ๋“ˆ์— ์ •์˜๋œ ์ตœ์ƒ์œ„ ์ด๋ฆ„๊ณผ ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค. + - `y`๋Š” ๊ณต๊ฐœ API์˜ ์ผ๋ถ€์ธ ๊ณตํ†ต ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„(์˜ˆ: 'features')๊ณผ ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค. + - `y`๋Š” ๋ถˆํŽธํ•  ์ •๋„๋กœ ๊ธด ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. + - `y`๋Š” ์ฝ”๋“œ ์ปจํ…์ŠคํŠธ์—์„œ ๋„ˆ๋ฌด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค(์˜ˆ: `from storage.file_system import options as fs_options`). +- `import y as z`๋ฅผ `z` ๊ฐ€ ๊ณต์‹์ ์ธ ์•ฝ์–ด์ธ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”(e.g., `import numpy as np`) - ์˜ˆ๋ฅผ๋“ค์–ด `sound.effects.echo`๋ชจ๋“ˆ์ด import ๋œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -42,3 +47,14 @@ - import๋œ๊ฒƒ๋“ค๊ณผ ๊ด€๋ จ์žˆ๋Š” ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์ง€๋งˆ์„ธ์š”. - ๋ชจ๋“ˆ์ด ๊ฐ™์€ ํŒจํ‚ค์ง€์— ์žˆ๋”๋ผ๋„ ์ „์ฒด ํŒจํ‚ค์ง€ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์„ธ์š”. - ์ด๋Š” ๋ฌด์‹ฌ์ฝ” ํŒจํ‚ค์ง€๋ฅผ ๋‘๋ฒˆ import ํ•˜๋Š”๊ฒƒ์„ ์˜ˆ๋ฐฉํ•˜๋Š” ๊ฒƒ์— ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. + + + +##### 2.2.4.1 ์˜ˆ์™ธ + +- ์ด ๊ทœ์น™์˜ ์˜ˆ์™ธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. + - ๋‹ค์Œ ๋ชจ๋“ˆ์˜ ์‹ฌ๋ณผ์€ ์ •์  ๋ถ„์„ ๋ฐ ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ์ง€์›ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + - [`typing` module](#typing-imports) + - [`collections.abc` module](#typing-imports) + - [`typing_extensions` module](https://github.com/python/typing_extensions/blob/main/README.md) + - [six.moves module](https://six.readthedocs.io/#module-six.moves)์˜ ๋ฆฌ๋‹ค์ด๋ ‰์…˜์ž…๋‹ˆ๋‹ค. diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.20 \355\230\204\353\214\200\354\235\230 \355\214\214\354\235\264\354\215\254.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.20 Modern Python.md" similarity index 58% rename from "Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.20 \355\230\204\353\214\200\354\235\230 \355\214\214\354\235\264\354\215\254.md" rename to "Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.20 Modern Python.md" index 26c355b..740f633 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.20 \355\230\204\353\214\200\354\235\230 \355\214\214\354\235\264\354\215\254.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.20 Modern Python.md" @@ -40,22 +40,4 @@ from __future__ import generator_stop ``` -- 2.7 ๋ฒ„์ „์„ ๊ณ„์† ์ง€์›ํ•ด์•ผํ•˜๋Š” ๋ถ€๋‹ด์ด ์žˆ๋Š” ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ - - ```python - from __future__ import absolute_import - from __future__ import division - from __future__ import print_function - ``` - - ์ž์„ธํ•œ ๋‚ด์šฉ์€ [Python future statement definitions](https://docs.python.org/3/library/__future__.html) ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. -- ์ฝ”๋“œ๊ฐ€ ์ถฉ๋ถ„ํžˆ ํ˜„๋Œ€์ ์ธ ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉ๋œ๋‹ค๋Š” ํ™•์‹ ์ด ๋“ค ๋•Œ๊นŒ์ง€ ์ด๋Ÿฌํ•œ import๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ๋งˆ์„ธ์š”. -- ํ˜„์žฌ ์ฝ”๋“œ์—์„œ ํŠน์ • ํ–ฅํ›„ import๋ฅผ ํ†ตํ•ด ํ™œ์„ฑํ™”๋˜๋Š” ๊ธฐ๋Šฅ์„ ํ˜„์žฌ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ ํŒŒ์ผ์— ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์œ ์ง€ํ•˜๋ฉด ๋‚˜์ค‘์— ์ฝ”๋“œ๊ฐ€ ์ด์ „ ๋™์ž‘์— ๋”ฐ๋ผ ์‹ค์ˆ˜๋กœ ์ˆ˜์ •๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -- ์ ์ ˆํ•˜๋‹ค๊ณ  ์ƒ๊ฐ๋˜๋Š” ๋‹ค๋ฅธ `from __future__` import ๋ฌธ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. -- 2.7๋ฒ„์ „ ๋‚ด์— ์—ฌ๋Ÿฌ ์œ„์น˜์—์„œ ๋„์ž…๋œ ์•”์‹œ์  ๊ธฐ๋ณธ ์ฝ”๋ฑ ๋ณ€ํ™˜ ๊ฒฐ๊ณผ๋กœ ์ธํ•ด ํ™•์‹คํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— 2.7๋ฒ„์ „์— ๋Œ€ํ•œ ๊ถŒ์žฅ ์‚ฌํ•ญ์— `unicode_literals`๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. -- ๋Œ€๋ถ€๋ถ„์˜ ์ด์ค‘ ๋ฒ„์ „ 2-3 ์ฝ”๋“œ๋Š” ํ•„์š”ํ•œ ๊ฒฝ์šฐ `b''` ์™€ `u''` q๋ฐ”ํŠธ์™€ ์œ ๋‹ˆ์ฝ”๋“œ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์„ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์•˜์Šต๋‹ˆ๋‹ค. - -##### six, future ๊ทธ๋ฆฌ๊ณ  past ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ - -- ํ”„๋กœ์ ํŠธ๊ฐ€ ์—ฌ์ „ํžˆ Python 2, 3 ๋ชจ๋‘์—์„œ ์‚ฌ์šฉ์„ ์ง€์›ํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ ์ ํ•ฉํ•˜๋‹ค๊ณ  ํŒ๋‹จ๋˜๋Š” ๋Œ€๋กœ [six](https://pypi.org/project/six/), [future](https://pypi.org/project/future/), ๋ฐ [past](https://pypi.org/project/past/) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ์ฝ”๋“œ๋ฅผ ๋” ๊นจ๋—ํ•˜๊ณ  ์‚ถ์„ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.21 Type \354\243\274\354\204\235.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.21 Type \354\243\274\354\204\235.md" index fed0b6b..1241ef4 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.21 Type \354\243\274\354\204\235.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.21 Type \354\243\274\354\204\235.md" @@ -3,8 +3,8 @@ ### 2.21 Type ์ฃผ์„ -- Python 3์—์„œ ํƒ€์ž…์˜ ์ •๋ณด๋ฅผ [PEP-484](https://www.python.org/dev/peps/pep-0484/)์˜ ์ฐธ๊ณ ํ•ด์„œ ์ฃผ์„์œผ๋กœ ๋‹ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋นŒ๋“œ ํ•  ๋•Œ [pytype](https://github.com/google/pytype)๊ฐ™์€ ํƒ€์ž…๊ฒ€์‚ฌ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- Type์— ๋Œ€ํ•œ ์ฃผ์„์€ ์†Œ์Šค ์•ˆ์ด๋‚˜ [stub pyi ํŒŒ์ผ](https://www.python.org/dev/peps/pep-0484/#stub-files)์— ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•˜๋ฉด ์ฃผ์„์€ ์†Œ์Šค์•ˆ์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์‚ฌ ๋˜๋Š” ํ™•์žฅ ๋ชจ๋“ˆ์—๋Š” pyi ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- Python์—์„œ ํƒ€์ž…์˜ ์ •๋ณด๋ฅผ [PEP-484](https://www.python.org/dev/peps/pep-0484/)์˜ ์ฐธ๊ณ ํ•ด์„œ ์ฃผ์„์œผ๋กœ ๋‹ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋นŒ๋“œ ํ•  ๋•Œ [pytype](https://github.com/google/pytype)๊ฐ™์€ ํƒ€์ž…๊ฒ€์‚ฌ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- Type์— ๋Œ€ํ•œ ์ฃผ์„์€ ์†Œ์Šค ์•ˆ์ด๋‚˜ [stub pyi ํŒŒ์ผ](https://peps.python.org/pep-0484/#stub-files)์— ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•˜๋ฉด ์ฃผ์„์€ ์†Œ์Šค์•ˆ์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์‚ฌ ๋˜๋Š” ํ™•์žฅ ๋ชจ๋“ˆ์—๋Š” pyi ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -13,21 +13,15 @@ - Type์˜ ์ฃผ์„(ํ˜น์€ Type ์ •๋ณด)์€ ํ•จ์ˆ˜๋‚˜ ๋ฉ”์„œ๋“œ์˜ ์ธ์ž๊ฐ’์ด๋‚˜ ๋ฐ˜ํ™˜๊ฐ’์ž…๋‹ˆ๋‹ค ```python - def func(a: int) -> List[int]: + def func(a: int) -> list[int]: ``` -- [PEP-526](https://www.python.org/dev/peps/pep-0526/)๊ตฌ๋ฌธ ์ฒ˜๋Ÿผ ๋ณ€์ˆ˜์˜ type์„ ์„ ์–ธํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +- [PEP-526](https://peps.python.org/pep-0526/)๊ตฌ๋ฌธ ์ฒ˜๋Ÿผ ๋ณ€์ˆ˜์˜ type์„ ์„ ์–ธํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ```python a: SomeType = some_func() ``` -- legacy Python version์„ ์ง€์›ํ•ด์•ผํ•œ๋‹ค๋ฉด ์ฝ”๋“œ์— type ์„ค๋ช…์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. - - ```python - a = some_func() # type: SomeType - ``` - #### 2.21.2 ์žฅ์  diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.3 package.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.3 package.md" index 844e3bc..318c6d1 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.3 package.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.3 package.md" @@ -31,7 +31,7 @@ import absl.flags from doctor.who import jodie - FLAGS = absl.flags.FLAGS + _FOO = absl.flags.DEFINE_string(...) ``` ```python @@ -39,7 +39,7 @@ from absl import flags from doctor.who import jodie - FLAGS = flags.FLAGS + _FOO = flags.DEFINE_string(...) ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ _(์ด ํŒŒ์ผ์€ `doctor/who/` ์— ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  `jodie.py`๋˜ํ•œ ์กด์žฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.)_ diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.4 \354\230\210\354\231\270\354\262\230\353\246\254.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.4 \354\230\210\354\231\270\354\262\230\353\246\254.md" index 48dbd10..c2b0ba4 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.4 \354\230\210\354\231\270\354\262\230\353\246\254.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.4 \354\230\210\354\231\270\354\262\230\353\246\254.md" @@ -30,10 +30,8 @@ ##### ์˜ˆ์™ธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค -- ์ ์ ˆํ•œ ๊ฒฝ์šฐ ๋‚ด์žฅ ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ์˜ˆ๋ฅผ ๋“ค์–ด, ๋งŒ์•ฝ ์–‘์ˆ˜๋ฅผ ์˜ˆ์ƒํ•˜๋Š”๋ฐ ์Œ์ˆ˜๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค๋ฉด `ValueError`๋ฅผ ๋ฐœ์ƒ์‹œ๋Š” ๊ฒƒ์ด ๊ทธ ์˜ˆ์ž…๋‹ˆ๋‹ค. -- ๊ณต๊ณต API์— ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฐ’์„ ๊ฒ€์ฆํ•˜๊ธฐ ์œ„ํ•ด `assert`๋ฌธ์„ ์‚ฌ์šฉํ•˜์ง€๋งˆ์„ธ์š”. -- `assert`๋Š” ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ์ด๋‚˜ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์ด๋ฒคํŠธ ๋ฐœ์ƒ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋‚ด๋ถ€์  ์ •ํ™•์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋‚˜์ค‘์— ์˜ˆ์™ธ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด, raise๋ฌธ์„ ์‹คํ–‰ํ•˜์„ธ์š”. +- ๋‚ด์žฅ ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์— ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋ฉด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•จ์ˆ˜ ์ธ์ž๋ฅผ ๊ฒ€์ฆํ•  ๋•Œ์™€ ๊ฐ™์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์˜ค๋ฅ˜๋‚˜ ์œ„๋ฐ˜๋œ ์ „์ œ์กฐ๊ฑด์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด `ValueError`๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์„ธ์š”. +- `assert` ๋ฌธ์„ ์กฐ๊ฑด๋ฌธ์ด๋‚˜ ์ „์ œ์กฐ๊ฑด ๊ฒ€์ฆ ๋Œ€์‹  ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. application logic์— ์ค‘์š”ํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. `assert`๋ฌธ์„ ์ œ๊ฑฐํ•ด๋„ ์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•œ๋‹ค๋ฉด, ๊ทธ๊ฒƒ์ด ๊ธฐ์ค€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. assert ์กฐ๊ฑด๋ฌธ์€ ํ‰๊ฐ€๋  ๊ฒƒ์ด๋ผ๊ณ  [๋ณด์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค](https://docs.python.org/3/reference/simple_stmts.html#the-assert-statement). [pytest](https://pytest.org)๊ธฐ๋ฐ˜์˜ ํ…Œ์ŠคํŠธ์—์„œ๋Š” `assert` ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋Œ€๊ฐ’์„ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ์ด ์ ์ ˆํ•˜๊ณ  ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -52,9 +50,10 @@ if minimum < 1024: raise ValueError(f'Min. port must be at least 1024, not {minimum}.') port = self._find_next_open_port(minimum) - if not port: + if port is None: raise ConnectionError( f'Could not connect to service on port {minimum} or higher.') + # ์ด ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ๋Š” ์ด assert์— ์˜์กดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. assert port >= minimum, ( f'Unexpected port {port} when minimum was {minimum}.') return port @@ -72,8 +71,10 @@ The new minimum port. """ assert minimum >= 1024, 'Minimum port must be at least 1024.' + # ์ด ์ฝ”๋“œ๋Š” ์ด์ „ assert์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. port = self._find_next_open_port(minimum) assert port is not None + # ๋ฐ˜ํ™˜ ๊ฐ’์— ๋Œ€ํ•œ ํƒ€์ž… ๊ฒ€์‚ฌ๋Š” assert์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. return port ``` diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.5 \353\263\200\352\262\275 \352\260\200\353\212\245\355\225\234 \354\240\204\354\227\255 \354\203\201\355\203\234.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.5 \353\263\200\352\262\275 \352\260\200\353\212\245\355\225\234 \354\240\204\354\227\255 \354\203\201\355\203\234.md" new file mode 100644 index 0000000..c55b77e --- /dev/null +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.5 \353\263\200\352\262\275 \352\260\200\353\212\245\355\225\234 \354\240\204\354\227\255 \354\203\201\355\203\234.md" @@ -0,0 +1,40 @@ + + + + + +### 2.5 ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ + +- ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. + + + +#### 2.5.1 ์ •์˜ + +- ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์ค‘ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“ˆ ์ˆ˜์ค€์˜ ๊ฐ’์ด๋‚˜ ํด๋ž˜์Šค ์†์„ฑ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. + + + +#### 2.5.2 ์žฅ์  + +- ๊ฐ€๋” ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + + + + + +#### 2.5.3 ๋‹จ์  + +- ์บก์Šํ™”๊ฐ€ ๊นจ์ง‘๋‹ˆ๋‹ค. + - ์ด๋Ÿฌํ•œ ์„ค๊ณ„๋Š” ์œ ํšจํ•œ ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด, ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ, ๋‘ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋™์‹œ์— ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(e.g., ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ค‘ ์ฐจ์ด๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ). ์ „์—ญ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์—์„œ๋„ ์œ ์‚ฌํ•œ ๋ฌธ์ œ๊ฐ€ ์‰ฝ๊ฒŒ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- ๋ชจ๋“ˆ์ด ์ฒ˜์Œ ์ž„ํฌํŠธ๋  ๋•Œ ์ „์—ญ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ํ• ๋‹น์ด ์ด๋ฃจ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์—, ๋ชจ๋“ˆ์˜ ๋™์ž‘์„ ์ž„ํฌํŠธ ์ค‘์— ๋ณ€๊ฒฝํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + + + + + +#### 2.5.4 ๊ฒฐ๋ก  + +- ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. + - ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋“œ๋ฌผ๊ฒŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์—”ํ‹ฐํ‹ฐ๋Š” ๋ชจ๋“ˆ ์ˆ˜์ค€์ด๋‚˜ ํด๋ž˜์Šค ์†์„ฑ์œผ๋กœ ์„ ์–ธํ•˜๊ณ , ์ด๋ฆ„ ์•ž์— `_`๋ฅผ ๋ถ™์—ฌ ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ์— ๋Œ€ํ•œ ์™ธ๋ถ€ ์ ‘๊ทผ์€ ๊ณต๊ฐœ ํ•จ์ˆ˜๋‚˜ ํด๋ž˜์Šค ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. [Naming](#s3.16-naming)๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์„ค๊ณ„ ์ด์œ ์— ๋Œ€ํ•ด์„œ๋Š” ์ฃผ์„์— ์„ค๋ช…ํ•˜๊ฑฐ๋‚˜ ๋งํฌ๋œ ๋ฌธ์„œ์—์„œ ์„ค๋ช…ํ•ด ์ฃผ์„ธ์š”. + - ๋ชจ๋“ˆ ์ˆ˜์ค€์˜ ์ƒ์ˆ˜๋Š” ํ—ˆ์šฉ๋˜๋ฉฐ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‚ด๋ถ€ ์šฉ๋„์˜ ์ƒ์ˆ˜์—๋Š” `_MAX_HOLY_HANDGRENADE_COUNT = 3`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , Public API ์ƒ์ˆ˜์—๋Š” `SIR_LANCELOTS_FAVORITE_COLOR = "blue"`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ƒ์ˆ˜๋Š” ๋ชจ๋‘ ๋Œ€๋ฌธ์ž์™€ ๋ฐ‘์ค„์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…๋ช…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. [Naming](#s3.16-naming)๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.5 \354\240\204\354\227\255\353\263\200\354\210\230.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.5 \354\240\204\354\227\255\353\263\200\354\210\230.md" deleted file mode 100644 index e633522..0000000 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.5 \354\240\204\354\227\255\353\263\200\354\210\230.md" +++ /dev/null @@ -1,34 +0,0 @@ - - -### 2.5 ์ „์—ญ ๋ณ€์ˆ˜ - -- ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. - - - -#### 2.5.1 ์ •์˜ - -- ๋ชจ๋“ˆ์ด๋‚˜ ํด๋ž˜์Šค ์†์„ฑ์œผ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค. - - - -#### 2.5.2 ์žฅ์  - -- ๊ฐ€๋” ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. - - - -#### 2.5.3 ๋‹จ์  - -- import๋˜๋Š” ๋™์•ˆ ๋ชจ๋“ˆ์˜ ๋™์ž‘์ด ๋ณ€๊ฒฝ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ „์—ญ ๋ณ€์ˆ˜์˜ ํ• ๋‹น์€ ๋ชจ๋“ˆ์„ ์ฒ˜์Œ import๋ฅผ ํ• ๋•Œ ์ˆ˜ํ–‰์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. - - - -#### 2.5.4 ๊ฒฐ๋ก  - -- ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. - -- ์ „์—ญ๋ณ€์ˆ˜๋Š” ๊ธฐ์ˆ ์ ์œผ๋กœ๋Š” ๋ณ€์ˆ˜์ด์ง€๋งŒ, module-level ์ƒ์ˆ˜๊ฐ€ ํ—ˆ์šฉ๋˜๊ณ  ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. -- ์˜ˆ๋ฅผ๋“ค์–ด `_MAX_HOLY_HANDGRENADE_COUNT = 3`. ์ƒ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ๋ชจ๋“  ๊ณต๋ฐฑ `_`๋ฅผ ๋„ฃ์–ด์„œ ์ด๋ฆ„์„ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋งŒ์•ฝ ์ „์—ญ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด module-level์—์„œ ์„ ์–ธ๋˜๊ณ  ๋ชจ๋“ˆ ๋‚ด๋ถ€์—์„œ ์ด๋ฆ„์— `_`๋ฅผ ๋ถ™์—ฌ์„œ ๋งŒ๋“ค์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์™ธ๋ถ€ ์ ‘๊ทผ์€ ๋ฐ˜๋“œ์‹œ public๋‹จ์œ„์˜ module-level ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ ๋™์ž‘๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. [Naming](#s3.16-naming)์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.6 \354\244\221\354\262\251.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.6 \354\244\221\354\262\251.md" index d8fa7eb..4c9be0b 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.6 \354\244\221\354\262\251.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.6 \354\244\221\354\262\251.md" @@ -18,7 +18,7 @@ #### 2.6.2 ์žฅ์  - ์ œํ•œ๋œ ์Šค์ฝ”ํ”„ ๋‚ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค์™€ ํ•จ์ˆ˜์˜ ์ •์˜๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. -- [ADT](http://www.google.com/url?sa=D&q=http://en.wikipedia.org/wiki/Abstract_data_type)๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ฐธ๊ณ ํ•˜์„ธ์š”. +- [ADT](https://ko.wikipedia.org/wiki/์ถ”์ƒ_์ž๋ฃŒํ˜•)๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ฐธ๊ณ ํ•˜์„ธ์š”. - ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.7 list_comprehensions.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.7 list_comprehensions.md" index 7820afb..e61736b 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.7 list_comprehensions.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.7 list_comprehensions.md" @@ -28,19 +28,17 @@ #### 2.7.4 ๊ฒฐ๋ก  -- ๋ณต์žกํ•˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ฐ๊ฐ์˜ ๋ถ€๋ถ„์€ ๋ฐ˜๋“œ์‹œ ํ•œ ๋ผ์ธ์—์„œ ๋๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- map, for๋ฌธ, filter ํ‘œํ˜„์‹์ด ๊ทธ ์˜ˆ์ž…๋‹ˆ๋‹ค. ์ค‘์ฒฉ for๋ฌธ์ด๋‚˜ filter๋ฌธ์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -- loop๋ฌธ์„ ํ†ตํ•ด ์ฝ”๋“œ๋ฅผ ๋‹จ์ˆœํ™” ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์ปดํ”„๋ฆฌํ—จ์…˜(comprehension)์€ ํ—ˆ์šฉ๋˜์ง€๋งŒ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ for ์ ˆ์ด๋‚˜ ํ•„ํ„ฐ ํ‘œํ˜„์‹์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ„๊ฒฐํ•จ๋ณด๋‹ค๋Š” ๊ฐ€๋…์„ฑ์„ ์šฐ์„ ์‹œํ•˜์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python result = [mapping_expr for value in iterable if filter_expr] - result = [{'key': value} for value in iterable - if a_long_filter_expression(value)] - - result = [complicated_transform(x) - for x in iterable if predicate(x)] + result = [ + is_valid(metric={'key': value}) + for value in interesting_iterable + if a_longer_filter_expression(value) + ] descriptive_name = [ transform({'key': key, 'value': value}, color='black') @@ -50,35 +48,30 @@ result = [] for x in range(10): - for y in range(5): - if x * y > 10: - result.append((x, y)) - - return {x: complicated_transform(x) - for x in long_generator_function(parameter) - if x is not None} - - squares_generator = (x**2 for x in range(10)) + for y in range(5): + if x * y > 10: + result.append((x, y)) + return { + x: complicated_transform(x) + for x in long_generator_function(parameter) + if x is not None + } + return (x**2 for x in range(10)) unique_names = {user.name for user in users if user is not None} - - eat(jelly_bean for jelly_bean in jelly_beans - if jelly_bean.color == 'black') ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - result = [complicated_transform( - x, some_argument=x+1) - for x in iterable if predicate(x)] - result = [(x, y) for x in range(10) for y in range(5) if x * y > 10] - return ((x, y, z) - for x in range(5) - for y in range(5) - if x != y - for z in range(5) - if y != z) + return ( + (x, y, z) + for x in range(5) + for y in range(5) + if x != y + for z in range(5) + if y != z + ) ``` diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.8 \352\270\260\353\263\270 \353\260\230\353\263\265\354\236\220\354\231\200 \354\227\260\354\202\260\354\236\220.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.8 \352\270\260\353\263\270 \353\260\230\353\263\265\354\236\220\354\231\200 \354\227\260\354\202\260\354\236\220.md" index dbca5ac..6d1fd56 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.8 \352\270\260\353\263\270 \353\260\230\353\263\265\354\236\220\354\231\200 \354\227\260\354\202\260\354\236\220.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.8 \352\270\260\353\263\270 \353\260\230\353\263\265\354\236\220\354\231\200 \354\227\260\354\202\260\354\236\220.md" @@ -21,7 +21,7 @@ #### 2.8.3 ๋‹จ์  -- ๋ฉ”์†Œ๋“œ ์ด๋ฆ„์„ ์ฝ์–ด๋„ ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ์œ ์ถ”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.(e.g. `has_key()`๋Š” ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.) ์ด๊ฑด ์ด์ ์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +- ๋ฉ”์†Œ๋“œ ์ด๋ฆ„์„ ์ฝ์–ด๋„ ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ์œ ์ถ”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.(๋ณ€์ˆ˜์— ํƒ€์ž… ์ฃผ์„์ด ์—†๋Š” ๊ฒฝ์šฐ) ์ด๊ฑด ์ด์ ์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -34,18 +34,14 @@ ```python for key in adict: ... - if key not in adict: ... if obj in alist: ... for line in afile: ... for k, v in adict.items(): ... - for k, v in six.iteritems(adict): ... ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python for key in adict.keys(): ... - if not adict.has_key(key): ... for line in afile.readlines(): ... - for k, v in dict.iteritems(): ... ``` diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.9 \354\240\234\353\204\210\353\240\210\354\235\264\355\204\260.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.9 \354\240\234\353\204\210\353\240\210\354\235\264\355\204\260.md" index c7aa226..1118025 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.9 \354\240\234\353\204\210\353\240\210\354\235\264\355\204\260.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/2.9 \354\240\234\353\204\210\353\240\210\354\235\264\355\204\260.md" @@ -22,10 +22,12 @@ #### 2.9.3 ๋‹จ์  -- ์—†์Šต๋‹ˆ๋‹ค. +- ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๋‚ด์˜ ์ง€์—ญ ๋ณ€์ˆ˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๊ฐ€ ๋ชจ๋‘ ์†Œ๋ชจ๋˜๊ฑฐ๋‚˜ ์ž์ฒด์ ์œผ๋กœ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜๋  ๋•Œ๊นŒ์ง€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. #### 2.9.4 ๊ฒฐ๋ก  - ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜์—์„œ docstring์— ๋Œ€ํ•ด "Returns:"๋ณด๋‹ค "Yields:"๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๊ฐ€ ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ์ž์›์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ, ์ •๋ฆฌ ์ž‘์—…์„ ๊ฐ•์ œ๋กœ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์ •๋ฆฌ ์ž‘์—…์„ ์ž˜ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €๋กœ ๊ฐ์‹ธ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค ([PEP-0533](https://peps.python.org/pep-0533/)). diff --git "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/ReadMe.md" "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/ReadMe.md" index cedd157..646f39a 100644 --- "a/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/ReadMe.md" +++ "b/Google Python Style Guide/2. Python \354\226\270\354\226\264 \352\267\234\354\271\231/ReadMe.md" @@ -38,7 +38,8 @@ - ๊ฒฝ๊ณ ๋ฅผ ๋„์šฐ์ง€ ์•Š๊ธฐ ์œ„ํ•ด, ์ฝ”๋“œ์— ๋ผ์ธ ๋‹จ์œ„๋กœ ์ฃผ์„์„ ๋‹ฌ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ```python - dict = 'something awful' # Bad Idea... pylint: disable=redefined-builtin + def do_PUT(self): # WSGI name, so pylint: disable=invalid-name + ... ``` - `pylint`์˜ ๊ฒฝ๊ณ ๋Š” ๊ฐ๊ฐ symbolic name(`empty-docstring`)์œผ๋กœ ๊ตฌ๋ณ„๋ฉ๋‹ˆ๋‹ค. @@ -54,7 +55,7 @@ - ๊ฐ ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•ด ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ์–ป๊ณ ์ž ํ•˜๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```shell - pylint --help-msg=C6409 + pylint --help-msg=invalid-name ``` - `pyling: disable-msg`๋Š” ์ด์ „์— ์‚ฌ์šฉํ–ˆ๋˜ ๋ฐฉ์‹์œผ๋กœ ์ด์ œ๋Š” ์‚ฌ์šฉ๋˜์ง€ ์•Š์œผ๋ฉฐ `pylint: disable`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. @@ -62,7 +63,7 @@ - ์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. ```python - def viking_cafe_order(spam: str, beans: str, eggs: Optional[str] = None) -> str: + def viking_cafe_order(spam: str, beans: str, eggs: str | None = None) -> str: del beans, eggs # Unused by vikings. return spam + spam + spam ``` @@ -74,7 +75,7 @@ ### 2.2 Imports -- `import`๋ฌธ์„ ์‚ฌ์šฉํ• ๋•Œ package์™€ module์— ์‚ฌ์šฉํ•˜๊ณ  ๊ฐœ๋ณ„ ํด๋ž˜์Šค๋‚˜ ํ•จ์ˆ˜์— ๋Œ€ํ•ด ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ [typing ๋ชจ๋“ˆ](#s3.19.12-imports), [typing_extensions module](https://github.com/python/typing/tree/master/typing_extensions)์—์„œ ๊ฐ€์ ธ์˜จ ํด๋ž˜์Šค ๋ฐ [six.moves module](https://six.readthedocs.io/#module-six.moves)์—์„œ์˜ ๋ฆฌ๋””๋ ‰์…˜์€ ์ด ๊ทœ์น™์—์„œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค. +- `import`๋ฌธ์€ ๊ฐœ๋ณ„ ํƒ€์ž…, ํด๋ž˜์Šค, ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ ํŒจํ‚ค์ง€์™€ ๋ชจ๋“ˆ์—๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”. (์ฃผ: ๊ฐœ๋ณ„ ํƒ€์ž…์€ ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•, ์‚ฌ์šฉ์ž ์ •์˜ ํด๋ž˜์Šค๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.) @@ -100,8 +101,13 @@ - `import x`๋ฅผ ํŒจํ‚ค์ง€์™€ ๋ชจ๋“ˆ์„ importํ• ๋•Œ ์‚ฌ์šฉํ•˜์„ธ์š”. - `from x import y`๋ฅผ `x`๊ฐ€ ํŒจํ‚ค์ง€์˜ ์ ‘๋‘์–ด์ด๊ณ  `y`๊ฐ€ ์ ‘๋‘์–ด๊ฐ€ ์—†๋Š” ๋ชจ๋“ˆ์ผ๋•Œ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ๋งŒ์•ฝ `y` ๋กœ ์ด๋ฆ„์ด ์ง€์–ด์ง„ ๋‘ ๋ชจ๋“ˆ์ด import๋˜๊ฑฐ๋‚˜ `y` ๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋„ˆ๋ฌด ๊ธด ์ด๋ฆ„์„ ๊ฐ€์กŒ๋‹ค๋ฉด `from x import y as z`๋ฅผ ์‚ฌ์šฉ์„ธ์š”. -- `import y as z`๋ฅผ `z` ๊ฐ€ ๊ณต์‹์ ์ธ ์•ฝ์–ด์ธ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”(e.g., `np` ๋Š” `numpy` ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.) +- ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ๋Š” `from x import y as z` ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + - `y`๋ผ๋Š” ์ด๋ฆ„์„ ๊ฐ€์ง„ ๋‘ ๊ฐœ์˜ ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. + - `y`๋Š” ํ˜„์žฌ ๋ชจ๋“ˆ์— ์ •์˜๋œ ์ตœ์ƒ์œ„ ์ด๋ฆ„๊ณผ ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค. + - `y`๋Š” ๊ณต๊ฐœ API์˜ ์ผ๋ถ€์ธ ๊ณตํ†ต ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„(์˜ˆ: 'features')๊ณผ ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค. + - `y`๋Š” ๋ถˆํŽธํ•  ์ •๋„๋กœ ๊ธด ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. + - `y`๋Š” ์ฝ”๋“œ ์ปจํ…์ŠคํŠธ์—์„œ ๋„ˆ๋ฌด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค(์˜ˆ: `from storage.file_system import options as fs_options`). +- `import y as z`๋ฅผ `z` ๊ฐ€ ๊ณต์‹์ ์ธ ์•ฝ์–ด์ธ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”(e.g., `import numpy as np`) - ์˜ˆ๋ฅผ๋“ค์–ด `sound.effects.echo`๋ชจ๋“ˆ์ด import ๋œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -115,6 +121,17 @@ - ๋ชจ๋“ˆ์ด ๊ฐ™์€ ํŒจํ‚ค์ง€์— ์žˆ๋”๋ผ๋„ ์ „์ฒด ํŒจํ‚ค์ง€ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์„ธ์š”. - ์ด๋Š” ๋ฌด์‹ฌ์ฝ” ํŒจํ‚ค์ง€๋ฅผ ๋‘๋ฒˆ import ํ•˜๋Š”๊ฒƒ์„ ์˜ˆ๋ฐฉํ•˜๋Š” ๊ฒƒ์— ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. + + +##### 2.2.4.1 ์˜ˆ์™ธ + +- ์ด ๊ทœ์น™์˜ ์˜ˆ์™ธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. + - ๋‹ค์Œ ๋ชจ๋“ˆ์˜ ์‹ฌ๋ณผ์€ ์ •์  ๋ถ„์„ ๋ฐ ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ์ง€์›ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + - [`typing` module](#typing-imports) + - [`collections.abc` module](#typing-imports) + - [`typing_extensions` module](https://github.com/python/typing_extensions/blob/main/README.md) + - [six.moves module](https://six.readthedocs.io/#module-six.moves)์˜ ๋ฆฌ๋‹ค์ด๋ ‰์…˜์ž…๋‹ˆ๋‹ค. + --- @@ -149,7 +166,7 @@ import absl.flags from doctor.who import jodie - FLAGS = absl.flags.FLAGS + _FOO = absl.flags.DEFINE_string(...) ``` ```python @@ -157,7 +174,7 @@ from absl import flags from doctor.who import jodie - FLAGS = flags.FLAGS + _FOO = flags.DEFINE_string(...) ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ _(์ด ํŒŒ์ผ์€ `doctor/who/` ์— ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  `jodie.py`๋˜ํ•œ ์กด์žฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.)_ @@ -205,10 +222,8 @@ ##### ์˜ˆ์™ธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค -- ์ ์ ˆํ•œ ๊ฒฝ์šฐ ๋‚ด์žฅ ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ์˜ˆ๋ฅผ ๋“ค์–ด, ๋งŒ์•ฝ ์–‘์ˆ˜๋ฅผ ์˜ˆ์ƒํ•˜๋Š”๋ฐ ์Œ์ˆ˜๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค๋ฉด `ValueError`๋ฅผ ๋ฐœ์ƒ์‹œ๋Š” ๊ฒƒ์ด ๊ทธ ์˜ˆ์ž…๋‹ˆ๋‹ค. -- ๊ณต๊ณต API์— ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฐ’์„ ๊ฒ€์ฆํ•˜๊ธฐ ์œ„ํ•ด `assert`๋ฌธ์„ ์‚ฌ์šฉํ•˜์ง€๋งˆ์„ธ์š”. -- `assert`๋Š” ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ์ด๋‚˜ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์ด๋ฒคํŠธ ๋ฐœ์ƒ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋‚ด๋ถ€์  ์ •ํ™•์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋‚˜์ค‘์— ์˜ˆ์™ธ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด, raise๋ฌธ์„ ์‹คํ–‰ํ•˜์„ธ์š”. +- ๋‚ด์žฅ ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์— ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋ฉด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•จ์ˆ˜ ์ธ์ž๋ฅผ ๊ฒ€์ฆํ•  ๋•Œ์™€ ๊ฐ™์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์˜ค๋ฅ˜๋‚˜ ์œ„๋ฐ˜๋œ ์ „์ œ์กฐ๊ฑด์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด `ValueError`๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์„ธ์š”. +- `assert` ๋ฌธ์„ ์กฐ๊ฑด๋ฌธ์ด๋‚˜ ์ „์ œ์กฐ๊ฑด ๊ฒ€์ฆ ๋Œ€์‹  ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. application logic์— ์ค‘์š”ํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. `assert`๋ฌธ์„ ์ œ๊ฑฐํ•ด๋„ ์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•œ๋‹ค๋ฉด, ๊ทธ๊ฒƒ์ด ๊ธฐ์ค€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. assert ์กฐ๊ฑด๋ฌธ์€ ํ‰๊ฐ€๋  ๊ฒƒ์ด๋ผ๊ณ  [๋ณด์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค](https://docs.python.org/3/reference/simple_stmts.html#the-assert-statement). [pytest](https://pytest.org)๊ธฐ๋ฐ˜์˜ ํ…Œ์ŠคํŠธ์—์„œ๋Š” `assert` ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋Œ€๊ฐ’์„ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ์ด ์ ์ ˆํ•˜๊ณ  ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -227,9 +242,10 @@ if minimum < 1024: raise ValueError(f'Min. port must be at least 1024, not {minimum}.') port = self._find_next_open_port(minimum) - if not port: + if port is None: raise ConnectionError( f'Could not connect to service on port {minimum} or higher.') + # ์ด ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ๋Š” ์ด assert์— ์˜์กดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. assert port >= minimum, ( f'Unexpected port {port} when minimum was {minimum}.') return port @@ -247,8 +263,10 @@ The new minimum port. """ assert minimum >= 1024, 'Minimum port must be at least 1024.' + # ์ด ์ฝ”๋“œ๋Š” ์ด์ „ assert์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. port = self._find_next_open_port(minimum) assert port is not None + # ๋ฐ˜ํ™˜ ๊ฐ’์— ๋Œ€ํ•œ ํƒ€์ž… ๊ฒ€์‚ฌ๋Š” assert์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. return port ``` @@ -261,16 +279,19 @@ --- + + + -### 2.5 ์ „์—ญ ๋ณ€์ˆ˜ +### 2.5 ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ -- ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. +- ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. #### 2.5.1 ์ •์˜ -- ๋ชจ๋“ˆ์ด๋‚˜ ํด๋ž˜์Šค ์†์„ฑ์œผ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค. +- ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์ค‘ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“ˆ ์ˆ˜์ค€์˜ ๊ฐ’์ด๋‚˜ ํด๋ž˜์Šค ์†์„ฑ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. @@ -279,21 +300,24 @@ - ๊ฐ€๋” ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + + #### 2.5.3 ๋‹จ์  -- import๋˜๋Š” ๋™์•ˆ ๋ชจ๋“ˆ์˜ ๋™์ž‘์ด ๋ณ€๊ฒฝ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ „์—ญ ๋ณ€์ˆ˜์˜ ํ• ๋‹น์€ ๋ชจ๋“ˆ์„ ์ฒ˜์Œ import๋ฅผ ํ• ๋•Œ ์ˆ˜ํ–‰์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +- ์บก์Šํ™”๊ฐ€ ๊นจ์ง‘๋‹ˆ๋‹ค. + - ์ด๋Ÿฌํ•œ ์„ค๊ณ„๋Š” ์œ ํšจํ•œ ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด, ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ, ๋‘ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋™์‹œ์— ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(e.g., ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ค‘ ์ฐจ์ด๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ). ์ „์—ญ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์—์„œ๋„ ์œ ์‚ฌํ•œ ๋ฌธ์ œ๊ฐ€ ์‰ฝ๊ฒŒ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- ๋ชจ๋“ˆ์ด ์ฒ˜์Œ ์ž„ํฌํŠธ๋  ๋•Œ ์ „์—ญ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ํ• ๋‹น์ด ์ด๋ฃจ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์—, ๋ชจ๋“ˆ์˜ ๋™์ž‘์„ ์ž„ํฌํŠธ ์ค‘์— ๋ณ€๊ฒฝํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + + #### 2.5.4 ๊ฒฐ๋ก  -- ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. - -- ์ „์—ญ๋ณ€์ˆ˜๋Š” ๊ธฐ์ˆ ์ ์œผ๋กœ๋Š” ๋ณ€์ˆ˜์ด์ง€๋งŒ, module-level ์ƒ์ˆ˜๊ฐ€ ํ—ˆ์šฉ๋˜๊ณ  ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. -- ์˜ˆ๋ฅผ๋“ค์–ด `_MAX_HOLY_HANDGRENADE_COUNT = 3`. ์ƒ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ๋ชจ๋“  ๊ณต๋ฐฑ `_`๋ฅผ ๋„ฃ์–ด์„œ ์ด๋ฆ„์„ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋งŒ์•ฝ ์ „์—ญ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด module-level์—์„œ ์„ ์–ธ๋˜๊ณ  ๋ชจ๋“ˆ ๋‚ด๋ถ€์—์„œ ์ด๋ฆ„์— `_`๋ฅผ ๋ถ™์—ฌ์„œ ๋งŒ๋“ค์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์™ธ๋ถ€ ์ ‘๊ทผ์€ ๋ฐ˜๋“œ์‹œ public๋‹จ์œ„์˜ module-level ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ ๋™์ž‘๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. [Naming](#s3.16-naming)์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. +- ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. + - ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋“œ๋ฌผ๊ฒŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์—”ํ‹ฐํ‹ฐ๋Š” ๋ชจ๋“ˆ ์ˆ˜์ค€์ด๋‚˜ ํด๋ž˜์Šค ์†์„ฑ์œผ๋กœ ์„ ์–ธํ•˜๊ณ , ์ด๋ฆ„ ์•ž์— `_`๋ฅผ ๋ถ™์—ฌ ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ์— ๋Œ€ํ•œ ์™ธ๋ถ€ ์ ‘๊ทผ์€ ๊ณต๊ฐœ ํ•จ์ˆ˜๋‚˜ ํด๋ž˜์Šค ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. [Naming](#s3.16-naming)๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ „์—ญ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์„ค๊ณ„ ์ด์œ ์— ๋Œ€ํ•ด์„œ๋Š” ์ฃผ์„์— ์„ค๋ช…ํ•˜๊ฑฐ๋‚˜ ๋งํฌ๋œ ๋ฌธ์„œ์—์„œ ์„ค๋ช…ํ•ด ์ฃผ์„ธ์š”. + - ๋ชจ๋“ˆ ์ˆ˜์ค€์˜ ์ƒ์ˆ˜๋Š” ํ—ˆ์šฉ๋˜๋ฉฐ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‚ด๋ถ€ ์šฉ๋„์˜ ์ƒ์ˆ˜์—๋Š” `_MAX_HOLY_HANDGRENADE_COUNT = 3`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , Public API ์ƒ์ˆ˜์—๋Š” `SIR_LANCELOTS_FAVORITE_COLOR = "blue"`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ƒ์ˆ˜๋Š” ๋ชจ๋‘ ๋Œ€๋ฌธ์ž์™€ ๋ฐ‘์ค„์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…๋ช…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. [Naming](#s3.16-naming)๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. --- @@ -316,7 +340,7 @@ #### 2.6.2 ์žฅ์  - ์ œํ•œ๋œ ์Šค์ฝ”ํ”„ ๋‚ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค์™€ ํ•จ์ˆ˜์˜ ์ •์˜๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. -- [ADT](http://www.google.com/url?sa=D&q=http://en.wikipedia.org/wiki/Abstract_data_type)๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ฐธ๊ณ ํ•˜์„ธ์š”. +- [ADT](https://ko.wikipedia.org/wiki/์ถ”์ƒ_์ž๋ฃŒํ˜•)๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ฐธ๊ณ ํ•˜์„ธ์š”. - ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. @@ -365,19 +389,17 @@ #### 2.7.4 ๊ฒฐ๋ก  -- ๋ณต์žกํ•˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ฐ๊ฐ์˜ ๋ถ€๋ถ„์€ ๋ฐ˜๋“œ์‹œ ํ•œ ๋ผ์ธ์—์„œ ๋๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- map, for๋ฌธ, filter ํ‘œํ˜„์‹์ด ๊ทธ ์˜ˆ์ž…๋‹ˆ๋‹ค. ์ค‘์ฒฉ for๋ฌธ์ด๋‚˜ filter๋ฌธ์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -- loop๋ฌธ์„ ํ†ตํ•ด ์ฝ”๋“œ๋ฅผ ๋‹จ์ˆœํ™” ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์ปดํ”„๋ฆฌํ—จ์…˜(comprehension)์€ ํ—ˆ์šฉ๋˜์ง€๋งŒ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ for ์ ˆ์ด๋‚˜ ํ•„ํ„ฐ ํ‘œํ˜„์‹์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ„๊ฒฐํ•จ๋ณด๋‹ค๋Š” ๊ฐ€๋…์„ฑ์„ ์šฐ์„ ์‹œํ•˜์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python result = [mapping_expr for value in iterable if filter_expr] - result = [{'key': value} for value in iterable - if a_long_filter_expression(value)] - - result = [complicated_transform(x) - for x in iterable if predicate(x)] + result = [ + is_valid(metric={'key': value}) + for value in interesting_iterable + if a_longer_filter_expression(value) + ] descriptive_name = [ transform({'key': key, 'value': value}, color='black') @@ -387,37 +409,32 @@ result = [] for x in range(10): - for y in range(5): - if x * y > 10: - result.append((x, y)) - - return {x: complicated_transform(x) - for x in long_generator_function(parameter) - if x is not None} - - squares_generator = (x**2 for x in range(10)) + for y in range(5): + if x * y > 10: + result.append((x, y)) + return { + x: complicated_transform(x) + for x in long_generator_function(parameter) + if x is not None + } + return (x**2 for x in range(10)) unique_names = {user.name for user in users if user is not None} - - eat(jelly_bean for jelly_bean in jelly_beans - if jelly_bean.color == 'black') ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - result = [complicated_transform( - x, some_argument=x+1) - for x in iterable if predicate(x)] - result = [(x, y) for x in range(10) for y in range(5) if x * y > 10] - return ((x, y, z) - for x in range(5) - for y in range(5) - if x != y - for z in range(5) - if y != z) + return ( + (x, y, z) + for x in range(5) + for y in range(5) + if x != y + for z in range(5) + if y != z + ) ``` --- @@ -444,7 +461,7 @@ #### 2.8.3 ๋‹จ์  -- ๋ฉ”์†Œ๋“œ ์ด๋ฆ„์„ ์ฝ์–ด๋„ ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ์œ ์ถ”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.(e.g. `has_key()`๋Š” ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.) ์ด๊ฑด ์ด์ ์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +- ๋ฉ”์†Œ๋“œ ์ด๋ฆ„์„ ์ฝ์–ด๋„ ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ์œ ์ถ”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.(๋ณ€์ˆ˜์— ํƒ€์ž… ์ฃผ์„์ด ์—†๋Š” ๊ฒฝ์šฐ) ์ด๊ฑด ์ด์ ์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -457,20 +474,16 @@ ```python for key in adict: ... - if key not in adict: ... if obj in alist: ... for line in afile: ... for k, v in adict.items(): ... - for k, v in six.iteritems(adict): ... ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python for key in adict.keys(): ... - if not adict.has_key(key): ... for line in afile.readlines(): ... - for k, v in dict.iteritems(): ... ``` --- @@ -498,13 +511,15 @@ #### 2.9.3 ๋‹จ์  -- ์—†์Šต๋‹ˆ๋‹ค. +- ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๋‚ด์˜ ์ง€์—ญ ๋ณ€์ˆ˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๊ฐ€ ๋ชจ๋‘ ์†Œ๋ชจ๋˜๊ฑฐ๋‚˜ ์ž์ฒด์ ์œผ๋กœ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜๋  ๋•Œ๊นŒ์ง€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. #### 2.9.4 ๊ฒฐ๋ก  - ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜์—์„œ docstring์— ๋Œ€ํ•ด "Returns:"๋ณด๋‹ค "Yields:"๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๊ฐ€ ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ์ž์›์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ, ์ •๋ฆฌ ์ž‘์—…์„ ๊ฐ•์ œ๋กœ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์ •๋ฆฌ ์ž‘์—…์„ ์ž˜ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €๋กœ ๊ฐ์‹ธ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค ([PEP-0533](https://peps.python.org/pep-0533/)). --- @@ -537,9 +552,7 @@ #### 2.10.4 ๊ฒฐ๋ก  -- ๋žŒ๋‹ค๋ฅผ ํ•œ ์ค„๋กœ ์‚ฌ์šฉํ•˜์„ธ์š”. ๋งŒ์•ฝ ์ฝ”๋“œ ๋‚ด๋ถ€์— ์žˆ๋Š” ๋žŒ๋‹ค ํ•จ์ˆ˜๊ฐ€ 60~80๊ธ€์ž ์ˆ˜ ์ •๋„๋กœ ๊ธธ๋‹ค๋ฉด ๊ทธ๊ฑด ์•„๋งˆ ๋” ์ผ๋ฐ˜์ ์ธ - [Lexical Scoping(๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ•‘)](#s2.16-lexical-scoping)์œผ๋กœ ์ •์˜ํ•˜๋Š”๊ฒŒ ๋‚˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. - +- ๋žŒ๋‹ค ํ•จ์ˆ˜๋Š” ํ—ˆ์šฉํ•˜์ง€๋งŒ, ๋žŒ๋‹ค ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์ฝ”๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ์ค„์— ๊ฑธ์น˜๊ฑฐ๋‚˜ 60-80์ž๋ฅผ ๋„˜๋Š” ๊ฒฝ์šฐ, ์ผ๋ฐ˜์ ์ธ [์ค‘์ฒฉ ํ•จ์ˆ˜](#s2.16-lexical-scoping)๋กœ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - ๊ณฑ์…ˆ ๊ฐ™์€ ์ผ๋ฐ˜ ์—ฐ์‚ฐ์ž์—์„œ๋Š” `operator`๋ชจ๋“ˆ ๋Œ€์‹ ์— ๋žŒ๋‹ค ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. - ์˜ˆ๋ฅผ ๋“ค์–ด, `operator.mul`์„ `lambda x,y : x * y` ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. @@ -649,7 +662,7 @@ def foo(a, b=None): if b is None: b = [] - def foo(a, b: Optional[Sequence] = None): + def foo(a, b: Sequence | None = None): if b is None: b = [] def foo(a, b: Sequence = ()): # tuples์€ ๋ถˆ๋ณ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. @@ -659,13 +672,16 @@ - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python + from absl import flags + _FOO = flags.DEFINE_string(...) + def foo(a, b=[]): ... - def foo(a, b=time.time()): # ๋ชจ๋“ˆ์ด ๋กœ๋“œ๊ฐ€ ๋  ๋•Œ์˜ ์‹œ๊ฐ„์ธ๊ฐ€??? + def foo(a, b=time.time()): # `b`๊ฐ€ ์ด ๋ชจ๋“ˆ์ด ๋กœ๋“œ๋œ ์‹œ๊ฐ„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ธ๊ฐ€์š”? ... - def foo(a, b=FLAGS.my_thing): # sys.argv๋Š” ์•„์ง ๊ตฌ๋ฌธ ๋ถ„์„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค... + def foo(a, b=_FOO.value): # sys.argv๋Š” ์•„์ง ๊ตฌ๋ฌธ ๋ถ„์„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค... ... - def foo(a, b: Mapping = {}): # ํ™•์ธ๋˜์ง€ ์•Š์€ ์ฝ”๋“œ๋กœ ์ „๋‹ฌ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค... + def foo(a, b: Mapping = {}): # ํ™•์ธ๋˜์ง€ ์•Š์€ ์ฝ”๋“œ๋กœ ์ „๋‹ฌ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ... ``` @@ -718,7 +734,7 @@ ### 2.14 True/False ํ‰๊ฐ€ -- ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ "์•”๋ฌต์ (implicit)" `false`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ "์•”๋ฌต์ (implicit)" `false`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. (๋ช‡ ๊ฐ€์ง€ ์ฃผ์˜์‚ฌํ•ญ์ด ์žˆ์ง€๋งŒ) @@ -818,7 +834,7 @@ #### 2.16.3 ๋‹จ์  -- ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๋ฒ„๊ทธ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. [PEP-0227](http://www.google.com/url?sa=D&q=http://www.python.org/dev/peps/pep-0227/)์—์„œ ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- [PEP-0227](https://peps.python.org/pep-0227)์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์ด ์˜ˆ์‹œ์™€ ๊ฐ™์ด ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๋ฒ„๊ทธ๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python i = 4 @@ -893,16 +909,16 @@ - Decorator๋Š” ๋ถ„๋ช…ํ•œ ์ด์ ์ด ์žˆ๋”๋ผ๋„ ํ˜„๋ช…ํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Decorator๋Š” import์™€ ๋ช…๋ช… ์ง€์นจ์„ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค. Decorator pydoc๋Š” decorator ํ•จ์ˆ˜ ์ž„์„ ๋ถ„๋ช…ํžˆ ๋ช…์‹œํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. dcorator๋ฅผ ์œ„ํ•œ ์œ ๋‹› ํ…Œ์ŠคํŠธ(unit test)๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. - Decorator(์˜ˆ. ํŒŒ์ผ, ์†Œ์ผ“, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋“ฑ) ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ (`pydoc` ํ˜น์€ ๊ธฐํƒ€ ๋„๊ตฌ๋ฅผ import ์‹œ๊ฐ„์— ๊ฐ€์ ธ์˜ฌ ๋•Œ) ์‚ฌ์šฉ ๋ชปํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ Decorator์˜ ์™ธ๋ถ€ ์˜์กด์„ฑ์„ ํ”ผํ•˜์„ธ์š”. ์œ ํšจํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง„ Decorator์€ ๋ชจ๋“  ๊ฒฝ์šฐ์— ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณด์žฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- Decorator๋Š” "Top level code"์˜ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์ผ ๋•Œ์—๋Š” [main](#s3.17-main) ํ•ญ๋ชฉ์— ์ž์„ธํ•œ ๋‚ด์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. +- Decorator๋Š” "Top-level code"์˜ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์ผ ๋•Œ์—๋Š” [main](#s3.17-main) ํ•ญ๋ชฉ์— ์ž์„ธํ•œ ๋‚ด์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. - ๊ธฐ์กด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ •์˜๋œ API์™€ ํ†ตํ•ฉํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ•์ œํ•˜์ง€ ์•Š๋Š” ํ•œ "staticmethod"๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. ๋Œ€์‹  ๋ชจ๋“ˆ ๋ ˆ๋ฒจ ํ•จ์ˆ˜๋ฅผ ์“ฐ์„ธ์š”. -- ํ”„๋กœ์„ธ์Šค ์ „์ฒด ์บ์‹œ ๋“ฑ ํ•„์š”ํ•œ global state๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋ช…๋ช…๋œ ์ƒ์„ฑ์ž ๋˜๋Š” ํด๋ž˜์Šค๋ณ„ ๋ฃจํ‹ด์„ ์ž‘์„ฑํ•  ๋•Œ๋งŒ "classmethod"๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- classmethod๋Š” ๋ช…๋ช…๋œ ์ƒ์„ฑ์ž๋ฅผ ์ž‘์„ฑํ•˜๊ฑฐ๋‚˜ ํ”„๋กœ์„ธ์Šค ์ „์ฒด ์บ์‹œ์™€ ๊ฐ™์€ ํ•„์ˆ˜ ์ „์—ญ ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ํด๋ž˜์Šค ํŠน์ • ๋ฃจํ‹ด์„ ์ž‘์„ฑํ•  ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”. --- ### 2.18 ์Šค๋ ˆ๋“œ -- ๋‚ด์žฅ๋œ ํƒ€์ž…์˜ ์›์ž์„ฑ์— ์˜์กดํ•˜์ง€ ๋งˆ์„ธ์š”. ๋”•์…”๋„ˆ๋ฆฌ์™€ ๊ฐ™์€ Python์˜ ๋‚ด์žฅ๋œ ํƒ€์ž…์€ ์›์ž ํ˜•ํƒœ๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ๋Ÿฌ์ง€ ์•Š์€ ๊ฒฝ์šฐ(์˜ˆ: `__hash__`์ด๋‚˜ `__eq__`๊ฐ€ Python ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„๋˜๋Š” ๊ฒฝ์šฐ)๋„ ์žˆ์œผ๋ฉฐ ์›์ž๋กœ ๋˜์–ด์žˆ๋‹ค๊ณ  ์‹ ๋ขฐํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์›์ž ๋ณ€์ˆ˜ ํ• ๋‹น์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. (๊ฒฐ๊ตญ, ๋”•์…”๋„ˆ๋ฆฌ์— ๋‹ฌ๋ ค์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค) ์Šค๋ ˆ๋“œ ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ต์‹ ํ•˜๋Š” ๋ฐ ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํ ๋ชจ๋“ˆ์˜ `Queue` ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด threading ๋ชจ๋“ˆ์ด๋‚˜ locking primitives๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. lower-level lock ๋Œ€์‹ ํ•ด Condition variables์™€ `threading.Condition`๋ฅผ ์„ ํ˜ธํ•˜์„ธ์š”. +- ๋‚ด์žฅ๋œ ํƒ€์ž…์˜ ์›์ž์„ฑ์— ์˜์กดํ•˜์ง€ ๋งˆ์„ธ์š”. ๋”•์…”๋„ˆ๋ฆฌ์™€ ๊ฐ™์€ Python์˜ ๋‚ด์žฅ๋œ ํƒ€์ž…์€ ์›์ž ํ˜•ํƒœ๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ๋Ÿฌ์ง€ ์•Š์€ ๊ฒฝ์šฐ(์˜ˆ: `__hash__`์ด๋‚˜ `__eq__`๊ฐ€ Python ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„๋˜๋Š” ๊ฒฝ์šฐ)๋„ ์žˆ์œผ๋ฉฐ ์›์ž๋กœ ๋˜์–ด์žˆ๋‹ค๊ณ  ์‹ ๋ขฐํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์›์ž ๋ณ€์ˆ˜ ํ• ๋‹น์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. (๊ฒฐ๊ตญ, ๋”•์…”๋„ˆ๋ฆฌ์— ๋‹ฌ๋ ค์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค) ์Šค๋ ˆ๋“œ ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ต์‹ ํ•˜๋Š” ๋ฐ ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ `queue` ๋ชจ๋“ˆ์˜ `Queue` ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด `threading` ๋ชจ๋“ˆ์ด๋‚˜ locking primitives๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. lower-level lock ๋Œ€์‹ ํ•ด Condition variables์™€ `threading.Condition`๋ฅผ ์„ ํ˜ธํ•˜์„ธ์š”. --- @@ -980,25 +996,7 @@ from __future__ import generator_stop ``` -- 2.7 ๋ฒ„์ „์„ ๊ณ„์† ์ง€์›ํ•ด์•ผํ•˜๋Š” ๋ถ€๋‹ด์ด ์žˆ๋Š” ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ - - ```python - from __future__ import absolute_import - from __future__ import division - from __future__ import print_function - ``` - - ์ž์„ธํ•œ ๋‚ด์šฉ์€ [Python future statement definitions](https://docs.python.org/3/library/__future__.html) ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. -- ์ฝ”๋“œ๊ฐ€ ์ถฉ๋ถ„ํžˆ ํ˜„๋Œ€์ ์ธ ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉ๋œ๋‹ค๋Š” ํ™•์‹ ์ด ๋“ค ๋•Œ๊นŒ์ง€ ์ด๋Ÿฌํ•œ import๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ๋งˆ์„ธ์š”. -- ํ˜„์žฌ ์ฝ”๋“œ์—์„œ ํŠน์ • ํ–ฅํ›„ import๋ฅผ ํ†ตํ•ด ํ™œ์„ฑํ™”๋˜๋Š” ๊ธฐ๋Šฅ์„ ํ˜„์žฌ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ ํŒŒ์ผ์— ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์œ ์ง€ํ•˜๋ฉด ๋‚˜์ค‘์— ์ฝ”๋“œ๊ฐ€ ์ด์ „ ๋™์ž‘์— ๋”ฐ๋ผ ์‹ค์ˆ˜๋กœ ์ˆ˜์ •๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -- ์ ์ ˆํ•˜๋‹ค๊ณ  ์ƒ๊ฐ๋˜๋Š” ๋‹ค๋ฅธ `from __future__` import ๋ฌธ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. -- 2.7๋ฒ„์ „ ๋‚ด์— ์—ฌ๋Ÿฌ ์œ„์น˜์—์„œ ๋„์ž…๋œ ์•”์‹œ์  ๊ธฐ๋ณธ ์ฝ”๋ฑ ๋ณ€ํ™˜ ๊ฒฐ๊ณผ๋กœ ์ธํ•ด ํ™•์‹คํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— 2.7๋ฒ„์ „์— ๋Œ€ํ•œ ๊ถŒ์žฅ ์‚ฌํ•ญ์— `unicode_literals`๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. -- ๋Œ€๋ถ€๋ถ„์˜ ์ด์ค‘ ๋ฒ„์ „ 2-3 ์ฝ”๋“œ๋Š” ํ•„์š”ํ•œ ๊ฒฝ์šฐ `b''` ์™€ `u''` q๋ฐ”ํŠธ์™€ ์œ ๋‹ˆ์ฝ”๋“œ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์„ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์•˜์Šต๋‹ˆ๋‹ค. - -##### six, future ๊ทธ๋ฆฌ๊ณ  past ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ - -- ํ”„๋กœ์ ํŠธ๊ฐ€ ์—ฌ์ „ํžˆ Python 2, 3 ๋ชจ๋‘์—์„œ ์‚ฌ์šฉ์„ ์ง€์›ํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ ์ ํ•ฉํ•˜๋‹ค๊ณ  ํŒ๋‹จ๋˜๋Š” ๋Œ€๋กœ [six](https://pypi.org/project/six/), [future](https://pypi.org/project/future/), ๋ฐ [past](https://pypi.org/project/past/) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ์ฝ”๋“œ๋ฅผ ๋” ๊นจ๋—ํ•˜๊ณ  ์‚ถ์„ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. --- @@ -1006,8 +1004,8 @@ ### 2.21 Type ์ฃผ์„ -- Python 3์—์„œ ํƒ€์ž…์˜ ์ •๋ณด๋ฅผ [PEP-484](https://www.python.org/dev/peps/pep-0484/)์˜ ์ฐธ๊ณ ํ•ด์„œ ์ฃผ์„์œผ๋กœ ๋‹ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋นŒ๋“œ ํ•  ๋•Œ [pytype](https://github.com/google/pytype)๊ฐ™์€ ํƒ€์ž…๊ฒ€์‚ฌ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- Type์— ๋Œ€ํ•œ ์ฃผ์„์€ ์†Œ์Šค ์•ˆ์ด๋‚˜ [stub pyi ํŒŒ์ผ](https://www.python.org/dev/peps/pep-0484/#stub-files)์— ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•˜๋ฉด ์ฃผ์„์€ ์†Œ์Šค์•ˆ์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์‚ฌ ๋˜๋Š” ํ™•์žฅ ๋ชจ๋“ˆ์—๋Š” pyi ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- Python์—์„œ ํƒ€์ž…์˜ ์ •๋ณด๋ฅผ [PEP-484](https://www.python.org/dev/peps/pep-0484/)์˜ ์ฐธ๊ณ ํ•ด์„œ ์ฃผ์„์œผ๋กœ ๋‹ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋นŒ๋“œ ํ•  ๋•Œ [pytype](https://github.com/google/pytype)๊ฐ™์€ ํƒ€์ž…๊ฒ€์‚ฌ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- Type์— ๋Œ€ํ•œ ์ฃผ์„์€ ์†Œ์Šค ์•ˆ์ด๋‚˜ [stub pyi ํŒŒ์ผ](https://peps.python.org/pep-0484/#stub-files)์— ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•˜๋ฉด ์ฃผ์„์€ ์†Œ์Šค์•ˆ์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์‚ฌ ๋˜๋Š” ํ™•์žฅ ๋ชจ๋“ˆ์—๋Š” pyi ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -1016,21 +1014,15 @@ - Type์˜ ์ฃผ์„(ํ˜น์€ Type ์ •๋ณด)์€ ํ•จ์ˆ˜๋‚˜ ๋ฉ”์„œ๋“œ์˜ ์ธ์ž๊ฐ’์ด๋‚˜ ๋ฐ˜ํ™˜๊ฐ’์ž…๋‹ˆ๋‹ค ```python - def func(a: int) -> List[int]: + def func(a: int) -> list[int]: ``` -- [PEP-526](https://www.python.org/dev/peps/pep-0526/)๊ตฌ๋ฌธ ์ฒ˜๋Ÿผ ๋ณ€์ˆ˜์˜ type์„ ์„ ์–ธํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +- [PEP-526](https://peps.python.org/pep-0526/)๊ตฌ๋ฌธ ์ฒ˜๋Ÿผ ๋ณ€์ˆ˜์˜ type์„ ์„ ์–ธํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ```python a: SomeType = some_func() ``` -- legacy Python version์„ ์ง€์›ํ•ด์•ผํ•œ๋‹ค๋ฉด ์ฝ”๋“œ์— type ์„ค๋ช…์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. - - ```python - a = some_func() # type: SomeType - ``` - #### 2.21.2 ์žฅ์  diff --git "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.10 \353\254\270\354\236\220\354\227\264.md" "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.10 \353\254\270\354\236\220\354\227\264.md" index b54023b..7b5d2ae 100644 --- "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.10 \353\254\270\354\236\220\354\227\264.md" +++ "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.10 \353\254\270\354\236\220\354\227\264.md" @@ -3,25 +3,24 @@ ### 3.10 Strings - ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋ชจ๋‘ ๋ฌธ์ž์—ด์ธ ๊ฒฝ์šฐ์—๋„ [f-string](https://docs.python.org/3/reference/lexical_analysis.html#f-strings), `format` ๋ฉ”์†Œ๋“œ๋‚˜ `%` ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํฌ๋ฉ”ํŒ…ํ•˜์„ธ์š”. -- ๋ฌผ๋ก  `+` ๋‚˜ `%` (๋˜๋Š” `format`) ๋ฅผ ์–ธ์ œ ์‚ฌ์šฉํ• ์ง€๋Š” ๊ฐœ๋ฐœ์ž์˜ ํŒ๋‹จ์— ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. -- ๋ฌธ์ž์—ด์„ ํ•ฉ์น˜๊ธฐ ์œ„ํ•ด `%` ๋˜๋Š” `format`์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. +- ๋ฌธ์ž์—ด ํฌ๋งทํŒ… ์˜ต์…˜ ์‚ฌ์ด์—์„œ ์ตœ์ƒ์˜ ํŒ๋‹จ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- `+`๋ฅผ ์‚ฌ์šฉํ•œ ๋‹จ์ผ join์€ ๊ดœ์ฐฎ์ง€๋งŒ, `+`๋ฅผ ์‚ฌ์šฉํ•œ ํฌ๋งทํŒ…์€ ํ”ผํ•˜์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - x = a + b + x = f'name: {name}; score: {n}' x = '%s, %s!' % (imperative, expletive) x = '{}, {}'.format(first, second) x = 'name: %s; score: %d' % (name, n) + x = 'name: %(name)s; score: %(score)d' % {'name':name, 'score':n} x = 'name: {}; score: {}'.format(name, n) - x = f'name: {name}; score: {n}' + x = a + b ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - x = '%s%s' % (a, b) # use + in this case - x = '{}{}'.format(a, b) # use + in this case x = first + ', ' + second x = 'name: ' + name + '; score: ' + str(n) ``` @@ -109,6 +108,9 @@ will collapse common leading spaces in each line.""") ``` +- ์—ฌ๊ธฐ์„œ ๋ฐฑ์Šฌ๋ž˜์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ [๋ช…์‹œ์ ์ธ ์ค„ ์ด์–ด์“ฐ๊ธฐ](#line-length)์— ๋Œ€ํ•œ ๊ธˆ์ง€๋ฅผ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- ์ด ๊ฒฝ์šฐ, ๋ฐฑ์Šฌ๋ž˜์‹œ๋Š” ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์—์„œ [์ค„๋ฐ”๊ฟˆ์„ ์ด์Šค์ผ€์ดํ”„](https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals)ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + #### 3.10.1 Logging @@ -159,7 +161,7 @@ ```python ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ: if not 0 <= p <= 1: - raise ValueError(f'Not a probability: {p!r}') + raise ValueError(f'Not a probability: {p=}') try: os.rmdir(workdir) except OSError as error: @@ -170,7 +172,7 @@ ```python ์ž˜๋ชป๋œ ์˜ˆ: if p < 0 or p > 1: # PROBLEM: also false for float('nan')! - raise ValueError(f'Not a probability: {p!r}') + raise ValueError(f'Not a probability: {p=}') try: os.rmdir(workdir) except OSError: diff --git "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.12 TODO \354\243\274\354\204\235.md" "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.12 TODO \354\243\274\354\204\235.md" index 65490df..1853b33 100644 --- "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.12 TODO \354\243\274\354\204\235.md" +++ "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.12 TODO \354\243\274\354\204\235.md" @@ -4,16 +4,27 @@ - ์ž„์‹œ์ , ์ž ์‹œ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์ฝ”๋“œ ๋˜๋Š” ์ข‹๊ธฐ๋Š” ํ•˜์ง€๋งŒ ์™„๋ฒฝํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ `TODO` ์ฃผ์„์„ ์‚ฌ์šฉํ•˜์„ธ์š”. -- `TODO` ์ฃผ์„์€ ๋Œ€๋ฌธ์ž๋กœ ๋˜์–ด์žˆ๋Š” `TODO` ๋ฌธ๊ตฌ๋กœ ์‹œ์ž‘ํ•˜๋ฉฐ ํ•ด๋‹น ์ฝ”๋“œ์— ๋Œ€ํ•œ ๊ฐ€์žฅ ๋†’์€ ์ดํ•ด๋„๋ฅผ ๊ฐ€์ง„ ์ธ๋ฌผ์˜ ์ด๋ฆ„, ์ด๋ฉ”์ผ ์ฃผ์†Œ ๋˜๋Š” ๋‹ค๋ฅธ ์‹ ์›๊ตฌ๋ถ„ ๋ฌธ๊ตฌ๋ฅผ ๊ด„ํ˜ธ์•ˆ์— ๋„ฃ์–ด ํฌํ•จํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์ด๊ฒƒ ๋’ค์— ๋ฌด์—‡์„ ํ•ด์•ผํ•˜๋Š” ์ง€์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. +- `TODO` ์ฃผ์„์€ ๋ชจ๋‘ ๋Œ€๋ฌธ์ž๋กœ ๋œ `TODO`๋กœ ์‹œ์ž‘ํ•˜๊ณ , ๋‹ค์Œ์— ์ฝœ๋ก ์„ ๋ถ™์ด๋ฉฐ, ๋งฅ๋ฝ์ด ํฌํ•จ๋œ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ๋งํฌ(์ด์ƒ์ ์œผ๋กœ๋Š” ๋ฒ„๊ทธ ์ฐธ์กฐ)๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๋ฒ„๊ทธ ์ฐธ์กฐ๊ฐ€ ์„ ํ˜ธ๋ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋ฒ„๊ทธ๋Š” ์ถ”์ ๋˜๋ฉฐ ํ›„์† ๋Œ“๊ธ€์ด ๋‹ฌ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +- ์ด ๋ฌธ๋งฅ ๋‹ค์Œ์— ํ•˜์ดํ”ˆ `-`์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์„ค๋ช… ๋ฌธ์ž์—ด์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”.. +- ๋ชฉ์ ์€ ์ผ๊ด€๋œ `TODO` ํ˜•์‹์„ ์œ ์ง€ํ•˜์—ฌ, ๋” ๋งŽ์€ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. -- ๋ชฉ์ ์€ `TODO`๊ฐ€ ์ผ๊ด€๋œ ํ˜•์‹์„ ์ด์šฉํ•˜์—ฌ ์ถ”ํ›„ ํ•„์š”ํ•œ ์„ธ๋ถ€์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. -- `TODO` ๋Š” ๋ณธ์ธ์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ฒ ๋‹ค๋Š” ์•ฝ์†์ด ์•„๋‹™๋‹ˆ๋‹ค. -- ๋”ฐ๋ผ์„œ `TODO` ๋ฅผ ๋งŒ๋“œ์…จ๋‹ค๋ฉด ๊ฑฐ์˜ ํ•ญ์ƒ ์ž‘์„ฑํ•œ ๋ณธ์ธ์˜ ์ด๋ฆ„์ด ๋“ค์–ด๊ฐ€์•ผ ํ•ฉ๋‹ˆ๋‹ค. + ```python + # TODO: crbug.com/192795 - Investigate cpufreq optimizations. + ``` -```python -# TODO(kl@gmail.com): Use a "*" here for string repetition. -# TODO(Zeke) Change this to use relations. -``` +- ์ด์ „ ์Šคํƒ€์ผ๋กœ, ์˜ˆ์ „์—๋Š” ๊ถŒ์žฅ๋˜์—ˆ์ง€๋งŒ ์ƒˆ๋กœ์šด ์ฝ”๋“œ์—์„œ๋Š” ์‚ฌ์šฉ์ด ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -- ๋งŒ์•ฝ ์ž‘์„ฑํ•œ `TODO` ๊ฐ€ "์ถ”ํ›„ ๋ฌด์—‡์„ ์ง„ํ–‰ํ•  ๊ฒƒ" ์ด๋ผ๋Š” ํ˜•์‹์„ ๋‹ด๊ณ  ์žˆ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ("2009๋…„ 11์›”๊นŒ์ง€") ์™€ ๊ฐ™์€ ๊ตฌ์ฒด์ ์ธ ๊ธฐ๊ฐ„์ด๋‚˜ ("๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ๊ฐ€ XML ์š”์ฒญ์„ ํ•ด๊ฒฐ ํ• ์ˆ˜ ์žˆ์„๋•Œ ์ด ์ฝ”๋“œ ์‚ญ์ œ") ์ฒ˜๋Ÿผ ๋ชฉ์ ์„ ํฌํ•จํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. + ```python + # TODO(crbug.com/192795): Investigate cpufreq optimizations. + # TODO(yourusername): Use a "\*" here for concatenation operator. + ``` + +- ๋ฌธ๋งฅ์œผ๋กœ ๊ฐœ์ธ์ด๋‚˜ ํŒ€์„ ์ฐธ์กฐํ•˜๋Š” TODO๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜์„ธ์š”. + + ```python + # TODO: @yourusername - File an issue and use a '*' for repetition. + ``` + +- `TODO`๊ฐ€ "๋ฏธ๋ž˜์˜ ์–ด๋Š ์‹œ์ ์— ๋ฌด์—‡์„ ํ•ด์•ผ ํ•œ๋‹ค"๋Š” ํ˜•์‹์ด๋ผ๋ฉด, ๋ฏธ๋ž˜์˜ ์ฝ”๋“œ ์œ ์ง€ ๊ด€๋ฆฌ์ž๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งค์šฐ ๊ตฌ์ฒด์ ์ธ ๋‚ ์งœ("2009๋…„ 11์›”๊นŒ์ง€")๋‚˜ ์‚ฌ๊ฑด("๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ๊ฐ€ XML ์š”์ฒญ์„ ํ•ด๊ฒฐ ํ• ์ˆ˜ ์žˆ์„๋•Œ ์ด ์ฝ”๋“œ ์‚ญ์ œ")์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์ด์Šˆ๋Š” ์ด๋ฅผ ์ถ”์ ํ•˜๋Š” ๋ฐ ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค. diff --git "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.13 import\355\230\225\354\213\235.md" "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.13 import\355\230\225\354\213\235.md" index 28c1607..fd875c1 100644 --- "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.13 import\355\230\225\354\213\235.md" +++ "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.13 import\355\230\225\354\213\235.md" @@ -2,14 +2,14 @@ ### 3.13 import ํ˜•์‹ -- imports๋Š” ๊ฐœ๋ณ„์ ์ธ ๋ผ์ธ์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค; [`typing` imports์— ๋Œ€ํ•œ ์˜ˆ์™ธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.](#s3.19.12-imports). +- imports๋Š” ๊ฐœ๋ณ„์ ์ธ ๋ผ์ธ์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค; [`typing` ๊ทธ๋ฆฌ๊ณ  `collections.abc` imports์— ๋Œ€ํ•œ ์˜ˆ์™ธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.](#s3.19.12-imports). - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python import os import sys - from typing import Mapping, Sequence + from typing import Any, NewType ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ @@ -21,7 +21,15 @@ - import๋Š” ๋ชจ๋“ˆ์˜ ์ฃผ์„ ๊ณผ docstring ๋ฐ”๋กœ ๋‹ค์Œ, ๋ชจ๋“ˆ ์ „์—ญ ๋ฐ ์ƒ์ˆ˜ ๋ฐ”๋กœ ์•ž ํŒŒ์ผ์˜ ๋งจ ์œ„์— ๋ฐฐ์น˜๋ฉ๋‹ˆ๋‹ค. - import๋Š” ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๊ฒƒ ๋ถ€ํ„ฐ ์ตœ์†Œํ•œ์˜ ์ผ๋ฐ˜์ ์ธ ๊ฒƒ๋“ค๊นŒ์ง€ ๋ฌถ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -1. ํŒŒ์ด์ฌ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ +1. Python์˜ **future** import ๋ฌธ + + ```python + from __future__ import annotations + ``` + + ์ž์„ธํ•œ ๋‚ด์šฉ์€ [์œ„](#from-future-imports)๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. + +2. ํŒŒ์ด์ฌ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ - import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -29,7 +37,7 @@ import sys ``` -2. [third-party](https://pypi.org/) +3. [third-party](https://pypi.org/) - ๋ชจ๋“ˆ์ด๋‚˜ ํŒจํ‚ค์ง€์˜ import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -37,7 +45,7 @@ import tensorflow as tf ``` -3. Code repository +4. Code repository - ์„œ๋ธŒ ํŒจํ‚ค์ง€์˜ import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -45,7 +53,7 @@ from otherproject.ai import mind ``` -4. ๋™์ผํ•œ top ๋ ˆ๋ฒจ์— ์†ํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํŠน์ •์„ importํ•˜๋Š” ๊ฒƒ์€ **๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค** +5. ๋™์ผํ•œ top ๋ ˆ๋ฒจ์— ์†ํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํŠน์ •์„ importํ•˜๋Š” ๊ฒƒ์€ **๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค** - ์„œ๋ธŒ ํŒจํ‚ค์ง€์˜ ํŒŒ์ผ import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. diff --git "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.16 \353\204\244\354\235\264\353\260\215.md" "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.16 \353\204\244\354\235\264\353\260\215.md" index ee536e6..744e67b 100644 --- "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.16 \353\204\244\354\235\264\353\260\215.md" +++ "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.16 \353\204\244\354\235\264\353\260\215.md" @@ -12,7 +12,9 @@ `global_var_name`, `instance_var_name`, `function_parameter_name`, -`local_var_name`. +`local_var_name`, +`query_proper_noun_for_thing`, +`send_acronym_via_https`. - ํ•จ์ˆ˜ ์ด๋ฆ„, ๋ณ€์ˆ˜ ์ด๋ฆ„, ๊ทธ๋ฆฌ๊ณ  ํŒŒ์ผ ์ด๋ฆ„์€ ์„ค๋ช…์ ์ด์—ฌ์•ผ ํ•˜๊ณ  ์•ฝ์–ด๋กœ ์ ๋Š” ์ผ์„ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ํŠนํžˆ ๋ชจํ˜ธํ•˜๊ฑฐ๋‚˜ ํ”„๋กœ์ ํŠธ์— ์ฐธ์—ฌํ•˜์ง€ ์•Š์€ ์‚ฌ๋žŒ๋“ค์ด ์ฝ์—ˆ์„ ๋•Œ ์ต์ˆ™ํ•˜์ง€ ์•Š์€ ์•ฝ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งˆ์„ธ์š”. ๊ทธ๋ฆฌ๊ณ  ์ ˆ๋Œ€ ๋‹จ์–ด์—์„œ ๊ธ€์ž๋ฅผ ์ง€์›Œ ์ค„์ด์ง€ ๋งˆ์„ธ์š”. @@ -23,15 +25,20 @@ #### 3.16.1 ํ”ผํ•ด์•ผ ํ•  ์ด๋ฆ„ -1. ์•„๋ž˜์™€ ๊ฐ™์€ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•œ ๋‹จ์ผ ๊ธ€์ž๋Š” ํ”ผํ•ฉ๋‹ˆ๋‹ค. +- ์•„๋ž˜์™€ ๊ฐ™์€ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•œ ๋‹จ์ผ ๊ธ€์ž๋Š” ํ”ผํ•ฉ๋‹ˆ๋‹ค. + + - counters์ด๋‚˜ iterators์—์„œ ์‚ฌ์šฉํ•  ๋•Œ (์˜ˆ. `i`, `j`, `k`, `v` ๋“ฑ) + - `try/except`๋ฌธ์—์„œ ์˜ˆ์™ธ ์‹๋ณ„์ž๋กœ `e`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ + - with๋ฌธ์˜ ํŒŒ์ผ ํ•ธ๋“ค์—์„œ `f`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ + - ์ œ์•ฝ ์กฐ๊ฑด์ด ์—†๋Š” ๋น„๊ณต์‹์ ์ธ [type variables](#typing-type-var)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ (e.g., `_T = TypeVar("_T"), _P = ParamSpec("_P")`) -- counters์ด๋‚˜ iterators์—์„œ ์‚ฌ์šฉํ•  ๋•Œ (์˜ˆ. `i`, `j`, `k`, `v` ๋“ฑ) -- `try/except`๋ฌธ์—์„œ ์˜ˆ์™ธ ์‹๋ณ„์ž๋กœ `e`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ -- with๋ฌธ์˜ ํŒŒ์ผ ํ•ธ๋“ค์—์„œ `f`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋‹จ์ผ ๊ธ€์ž๋ฅผ ๋‚จ์šฉํ•˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋งํ•ด์„œ ์„œ์ˆ ์„ฑ์€ ์ด๋ฆ„์˜ ๊ฐ€์‹œ์„ฑ ๋ฒ”์œ„์— ๋น„๋ก€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `i`๋Š” 5ํ–‰ ์ฝ”๋“œ ๋ธ”๋ก์— ์ ํ•ฉํ•œ ์ด๋ฆ„์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ค‘์ฒฉ๋œ ์—ฌ๋Ÿฌ ๋ฒ”์œ„ ๋‚ด์—์„œ๋Š” ๋„ˆ๋ฌด ๋ชจํ˜ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + - package/module ์ด๋ฆ„์—์„œ dashes(`-`)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ - `__์ด์ค‘_์„ ํ–‰_๋ฐ_ํ›„ํ–‰_๋ฐ‘์ค„__` ์ด๋ฆ„์„ ์‚ฌ์šฉํ•  ๋•Œ (Python์—์„œ ์˜ˆ์•ฝ์–ด) + - ์›๋ณธ์— ์—†๋Š” ์ถ”๊ฐ€ ์„ค๋ช… : double leading and trailing underscore : (์•ž ๋’ค๋กœ \_๊ฐ€ 2๊ฐœ์”ฉ ์žˆ๋Š”๊ฒƒ e.g **name**, **init**) + - ๊ณต๊ฒฉ์ ์ธ ๋‹จ์–ด - ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ณ€์ˆ˜ ํƒ€์ž…์„ ํฌํ•จํ•˜๋Š” ์ด๋ฆ„ (์˜ˆ : `id_to_name_dict`) @@ -43,16 +50,20 @@ - "Internal"๋Š” ๋ชจ๋“ˆ์˜ ๋‚ด๋ถ€ ๋˜๋Š” ํด๋ž˜์Šค ๋‚ด์—์„œ protected ๋˜๋Š” private๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. - ๋‹จ์ผ ๋ฐ‘์ค„(`_`)์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ชจ๋“ˆ ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜๋ฅผ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ง€์›์ด ์žˆ์Šต๋‹ˆ๋‹ค. (linters๋Š” ๋ณดํ˜ธ๋œ ๋ฉค๋ฒ„ ์ ‘๊ทผ์— ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.) +- ๋‹จ์ผ ์–ธ๋”์Šค์ฝ”์–ด(`_`)๋ฅผ ์ ‘๋‘์‚ฌ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ชจ๋“ˆ ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜ ๋ณดํ˜ธ๋ฅผ ์œ„ํ•œ ์ผ๋ถ€ ์ง€์›์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค (linters๊ฐ€ ๋ณดํ˜ธ๋œ ๋ฉค๋ฒ„ ์ ‘๊ทผ์„ ๊ฒฝ๊ณ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค). ๊ทธ๋Ÿฌ๋‚˜ ์œ ๋‹› ํ…Œ์ŠคํŠธ๊ฐ€ ํ…Œ์ŠคํŠธ ์ค‘์ธ ๋ชจ๋“ˆ์˜ ๋ณดํ˜ธ๋œ ์ƒ์ˆ˜์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์€ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. - ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋‚˜ ๋ฉ”์†Œ๋“œ์— ์ด์ค‘ ๋ฐ‘์ค„(`__` : dunder)์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ณ€์ˆ˜๋‚˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•ด๋‹น ํด๋ž˜์Šค์— ๋Œ€ํ•ด ํšจ๊ณผ์ ์œผ๋กœ private ๋ฉ๋‹ˆ๋‹ค. - ๊ฐ€๋…์„ฑ๊ณผ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ์„ฑ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ณ  _์‹ค์ œ๋กœ_ ๋น„๊ณต๊ฐœ๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. - ํ•˜๋‚˜์˜ ๋ฐ‘์ค„์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. - ๋ชจ๋“ˆ์— ๊ด€๋ จ ํด๋ž˜์Šค์™€ top-level ํ•จ์ˆ˜๋ฅผ ํ•จ๊ป˜ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. - ์ž๋ฐ”์™€๋Š” ๋‹ค๋ฅด๊ฒŒ ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ์— ๋Œ€ํ•ด ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋กœ ์ œํ•œ์„ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. - CapWords(๋‹จ์–ด์˜ ์ฒซ ๊ธ€์ž๋ฅผ ๋Œ€๋ฌธ์ž๋กœ ํ•˜๋Š” ๋ฐฉ์‹)์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์ด \_with_under.py ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ์†Œ๋ฌธ์ž๋กœ ํ•ฉ๋‹ˆ๋‹ค. + - ๋น„๋ก ๋ช‡๋ช‡ ์˜ค๋ž˜๋œ ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์ด CapWords.py์ผ์ง€๋ผ๋„ ์ด์ œ๋Š” ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์„ class์ด๋ฆ„์— ๋”ฐ๋ผ ์ง“๊ฒŒ ๋˜๋ฉด ํ˜ผ๋ž€์Šค๋Ÿฌ์šฐ๋ฏ€๋กœ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. (e.g "์ž ๊น๋งŒ, -- ๋‚ด๊ฐ€ `import StringIO`๋ฅผ ํ•œ๊ฑฐ์•ผ ์•„๋‹ˆ๋ฉด `from StringIO import StringIO`๋ฅผ ํ•œ๊ฑฐ์•ผ ?" ๊ฐ™์€ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.) -- ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ CapWord๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ "test"๋กœ ์‹œ์ž‘ํ•˜๋Š” _unittest_ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์— Undercore๊ฐ€ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - - ํ•œ ๊ฐ€์ง€ ๊ฐ€๋Šฅํ•œ ํŒจํ„ด์€ `test_`๋กœ, ์˜ˆ๋ฅผ ๋“ค์–ด `testPop_EmptyStack`๊ฐ™์€ ํŒจํ„ด์€ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. - - test ๋ฉ”์„œ๋“œ์— ์— ์ด๋ฆ„์„ ๋ถ™์ด๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•์€ ์—†์Šต๋‹ˆ๋‹ค. + +- ์ƒˆ๋กœ์šด ์œ ๋‹› ํ…Œ์ŠคํŠธ ํŒŒ์ผ์€ PEP 8์„ ์ค€์ˆ˜ํ•˜๋Š” ์†Œ๋ฌธ์ž์™€ ์–ธ๋”์Šค์ฝ”์–ด ๋ฐฉ์‹์˜ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. + - ์˜ˆ๋ฅผ ๋“ค์–ด, `test**`์™€ ๊ฐ™์€ ํ˜•์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + - ์ผ๊ด€์„ฑ์„ ์œ„ํ•ด(\*) ์ด์ „ ๋ชจ๋“ˆ์—์„œ CapWords ํ•จ์ˆ˜ ์ด๋ฆ„์„ ๋”ฐ๋ฅด๋Š” ๊ฒฝ์šฐ, `test`๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ด๋ฆ„์— ๋…ผ๋ฆฌ์  ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด ์–ธ๋”์Šค์ฝ”์–ด๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + - ํ•˜๋‚˜์˜ ๊ฐ€๋Šฅํ•œ ํŒจํ„ด์€ `test_`์ž…๋‹ˆ๋‹ค. diff --git "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.19 Type \354\243\274\354\204\235 \353\260\251\353\262\225.md" "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.19 Type \354\243\274\354\204\235 \353\260\251\353\262\225.md" index 2502927..4ea4d38 100644 --- "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.19 Type \354\243\274\354\204\235 \353\260\251\353\262\225.md" +++ "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.19 Type \354\243\274\354\204\235 \353\260\251\353\262\225.md" @@ -6,9 +6,24 @@ #### 3.19.1 ์ผ๋ฐ˜์ ์ธ ๊ทœ์น™ -- [PEP-484](https://www.python.org/dev/peps/pep-0484/)์„ ์ฝ์œผ์„ธ์š”. -- ๋ฉ”์„œ๋“œ์—์„œ๋Š” `self`, `cls`๋Š” Type์˜ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—์„œ๋งŒ ์ฃผ์„์„ ๋‹ฌ์•„์•ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ) `@classmethod def create(cls: Type[T]) -> T: return cls()` +- [PEP-484](https://peps.python.org/pep-0484/)์„ ์ฝ์œผ์„ธ์š”. + +- `self` ๋˜๋Š” `cls`์— ์ฃผ์„์„ ๋‹ฌ ํ•„์š”๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์—†์Šต๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ ํƒ€์ž… ์ •๋ณด๋ฅผ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ [`Self`](https://docs.python.org/3/library/typing.html#typing.Self)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + ```python + from typing import Self + class BaseClass: + @classmethod + def create(cls) -> Self: + ... + def difference(self, other: Self) -> float: + ... + ``` + +- ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, `__init__`์˜ ๋ฐ˜ํ™˜ ๊ฐ’์— ์ฃผ์„์„ ๋‹ฌ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค (์—ฌ๊ธฐ์„œ `None`๋งŒ ์œ ํšจํ•œ ์˜ต์…˜์ž…๋‹ˆ๋‹ค). + - ๋ชจ๋“  ๋ณ€์ˆ˜๋‚˜ ๋ฐ˜ํ™˜๋˜๋Š” Type์ด ์ •ํ•ด์ง€์ง€ ์•Š์•˜๋‹ค๋ฉด `Any`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + - ๋ชจ๋“ˆ์—์„œ ๋ชจ๋“  ํ•จ์ˆ˜์— ์ฃผ์„์„ ๋‹ฌ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. - Public API์—๋Š” ์ตœ์†Œํ•œ์˜ ์ฃผ์„์„ ๋‹ต๋‹ˆ๋‹ค. - ํŒ๋‹จ๋ ฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•œํŽธ์œผ๋กœ๋Š” ์•ˆ์ „์„ฑ๊ณผ ๋ช…ํ™•์„ฑ, ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ํ•œํŽธ์œผ๋กœ๋Š” ์œ ์—ฐ์„ฑ ์‚ฌ์ด์˜ ๊ท ํ˜•์„ ์ž˜ ์žก์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -23,12 +38,15 @@ - ๊ธฐ์กด์˜ [๋“ค์—ฌ์“ฐ๊ธฐ](#s3.4-indentation) ๊ทœ์น™์„ ๋”ฐ๋ฅด์„ธ์š”. - ์ฃผ์„์ฒ˜๋ฆฌํ•˜๊ณ ๋‚˜์„œ ๋งŽ์€ ํ•จ์ˆ˜๋Š” "ํ•œ ์ค„์— ํ•˜๋‚˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ"๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +- ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ๋ณ„๋„์˜ ์ค„์— ํ‘œ์‹œ๋˜๋„๋ก ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด, ๋งˆ์ง€๋ง‰ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋’ค์— ์‰ผํ‘œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python - def my_method(self, - first_var: int, - second_var: Foo, - third_var: Optional[Bar]) -> int: + def my_method( + self, + first_var: int, + second_var: Foo, + third_var: Bar | None, + ) -> int: ... ``` @@ -40,23 +58,25 @@ ``` - ํ•จ์ˆ˜ ์ด๋ฆ„, ๋งˆ์ง€๋ง‰ ๋งค๊ฐœ ๋ณ€์ˆ˜ ๋ฐ ๋ฆฌํ„ด Type์˜ ์กฐํ•ฉ์ด ๋„ˆ๋ฌด ๊ธธ๋ฉด ์ƒˆ ํ–‰์—์„œ 4๋งŒํผ ๋“ค์—ฌ ์“ฐ๊ธฐ๋ฉ๋‹ˆ๋‹ค. +- ์ค„ ๋ฐ”๊ฟˆ์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๋ณ„๋„์˜ ์ค„์— ๋ฐฐ์น˜ํ•˜๊ณ , ๋‹ซ๋Š” ๊ด„ํ˜ธ๋ฅผ `def`์™€ ์ •๋ ฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ```python def my_method( - self, first_var: int) -> Tuple[MyLongType1, MyLongType1]: + self, + other_arg: MyLongType | None, + ) -> tuple[MyLongType1, MyLongType1]: ... ``` -๋ฆฌํ„ด ์œ ํ˜•์ด ๋งˆ์ง€๋ง‰ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๊ฐ™์€ ๋ผ์ธ์— ๋งž์ง€ ์•Š์„ ๊ฒฝ์šฐ, ์„ ํ˜ธ๋˜๋Š” ๋ฐฉ๋ฒ•์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ 4๋งŒํผ ์ƒˆ ๋ผ์ธ์— ๋“ค์—ฌ์“ฐ๊ณ  ๋‹ซํžˆ๋Š” ๊ด„ํ˜ธ๋ฅผ "def"์™€ ์ •๋ ฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค. +- ์„ ํƒ์ ์œผ๋กœ, ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๋งˆ์ง€๋ง‰ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๊ฐ™์€ ์ค„์— ๋ฐฐ์น˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -- ๋ฐ˜ํ™˜ Type์ด ๋งˆ์ง€๋ง‰ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๊ฐ™์€ ์ค„์ด ์•„๋‹ ๋•Œ, ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ 4๋งŒํผ ์ƒˆ ๋ผ์ธ์— ๋“ค์—ฌ์“ฐ๊ณ  ๋‹ซํžˆ๋Š” ๊ด„ํ˜ธ๋ฅผ `def`์™€ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค. - - - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ + - ๊ดœ์ฐฎ์€ ์˜ˆ ```python def my_method( - self, **kw_args: Optional[MyLongType] - ) -> Dict[OtherLongType, MyLongType]: + self, + first_var: int, + second_var: int) -> dict[OtherLongType, MyLongType]: ... ``` @@ -66,8 +86,8 @@ ```python def my_method(self, - **kw_args: Optional[MyLongType] - ) -> Dict[OtherLongType, MyLongType]: + other_arg: MyLongType | None, + ) -> dict[OtherLongType, MyLongType]: ... ``` @@ -77,10 +97,11 @@ ```python def my_method( self, - first_var: Tuple[List[MyLongType1], - List[MyLongType2]], - second_var: List[Dict[ - MyLongType3, MyLongType4]]) -> None: + first_var: tuple[list[MyLongType1], + list[MyLongType2]], + second_var: list[dict[ + MyLongType3, MyLongType4]], + ) -> None: ... ``` @@ -111,23 +132,34 @@ #### 3.19.3 ์ „๋ฐฉ์„ ์–ธ -- ์•„์ง ์ •์˜๋˜์ง€ ์•Š์€ ๋™์ผํ•œ ๋ชจ๋“ˆ์˜ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ(์˜ˆ, ํด๋ž˜์Šค ์„ ์–ธ ๋‚ด์— ํด๋ž˜์Šค๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋˜๋Š” ์•„๋ž˜์— ์ •์˜๋œ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ) `from __future__ import annotations`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ์—๋Š” ์ฃผ์„์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํด๋ž˜์Šค ์ด๋ฆ„์— ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์•„์ง ์ •์˜๋˜์ง€ ์•Š์€ ํด๋ž˜์Šค ์ด๋ฆ„(์˜ˆ๋ฅผ ๋“ค์–ด, ํด๋ž˜์Šค ์„ ์–ธ ๋‚ด๋ถ€์—์„œ ํด๋ž˜์Šค ์ด๋ฆ„์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜ ์ฝ”๋“œ์—์„œ ๋‚˜์ค‘์— ์ •์˜๋œ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ)์„ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒฝ์šฐ, `from __future__ import annotations`๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํด๋ž˜์Šค ์ด๋ฆ„์„ ๋ฌธ์ž์—ด๋กœ ์‚ฌ์šฉํ•˜์„ธ์š”. -```python -from __future__ import annotations + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ -class MyClass: + ```python + from __future__ import annotations - def __init__(self, stack: Sequence[MyClass]) -> None: -``` + class MyClass: + def __init__(self, stack: Sequence[MyClass], item: OtherClass) -> None: + + class OtherClass: + ... + ``` + + ```python + class MyClass: + def __init__(self, stack: Sequence['MyClass'], item: 'OtherClass') -> None: + + class OtherClass: + ... + ``` #### 3.19.4 ๊ธฐ๋ณธ ๊ฐ’ - PEP-008์— ๋”ฐ๋ผ ์œ ํ˜• ์ฃผ์„๊ณผ ๊ธฐ๋ณธ๊ฐ’์ด ๋ชจ๋‘ ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฒฝ์šฐ "=" \_ only" ์ฃผ์œ„์— ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. -- [PEP-008](https://www.python.org/dev/peps/pep-0008/#other-recommendations)์— ๋”ฐ๋ผ Type ์ฃผ์„๊ณผ ๊ธฐ๋ณธ ๊ฐ’์ด ๋ชจ๋‘ ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฒฝ์šฐ `=` _only_ ์ฃผ์œ„์— ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์„ธ์š”, +- [PEP-008](https://peps.python.org/pep-0008/#other-recommendations)์— ๋”ฐ๋ผ Type ์ฃผ์„๊ณผ ๊ธฐ๋ณธ ๊ฐ’์ด ๋ชจ๋‘ ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฒฝ์šฐ `=` _only_ ์ฃผ์œ„์— ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์„ธ์š”, - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -147,19 +179,20 @@ class MyClass: #### 3.19.5 NoneType -- ํŒŒ์ด์ฌํ˜•์—์„œ ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ํผ์ŠคํŠธํด๋ž˜์Šคํ˜•์ด๋ฉฐ, ํƒ€์ดํ•‘์„ ์œ„ํ•ด ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ๋…ธ๋„คํƒ€์ž…(NoneType)์˜ ๋ณ„์นญ์ด๋‹ค. ๋…ผ์Ÿ์ด '์—†์Œ'์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค! ์œ ๋‹ˆ์˜จ(Union)์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋‹ค๋ฅธ ์œ ํ˜•์ด ํ•˜๋‚˜๋งŒ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” ์„ ํƒ์‚ฌํ•ญ(Option)์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. +- ํŒŒ์ด์ฌํ˜•์—์„œ ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ํผ์ŠคํŠธํด๋ž˜์Šคํ˜•์ด๋ฉฐ, ํƒ€์ดํ•‘์„ ์œ„ํ•ด ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ๋…ธ๋„คํƒ€์ž…(NoneType)์˜ ๋ณ„์นญ์ด๋‹ค. +- ์ธ์ž๊ฐ€ `None`์ด ๋  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ, ์ด๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค! +- ์ƒˆ๋กœ์šด Python 3.10+ ์ฝ”๋“œ์—์„œ๋Š” `|` ์œ ๋‹ˆ์˜จ ํƒ€์ž… ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋˜๋ฉฐ, ์ด์ „์—๋Š” `Optional`๊ณผ `Union` ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -- ํŒŒ์ด์ฌ ํƒ€์ž… ์‹œ์Šคํ…œ์—์„œ `NoneType`์€ "first class" Type ์ด๋ฉฐ ์ž‘์„ฑ์„ ์œ„ํ•ด `None`์€ `NoneType`์˜ alias(๋ณ„์นญ)์ž…๋‹ˆ๋‹ค. ์ธ์ž๋Š” `None`์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์„ ์–ธ์„ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค! `Union`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‹ค๋ฅธ Type์ด ํ•˜๋‚˜๋งŒ ์žˆ๋Š” ๊ฒฝ์šฐ `Optional`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. - -- ์•”์‹œ์  `Optional` ๋Œ€์‹  ๋ช…์‹œ์  `Optional` ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. PEP 484 ์ด์ „ ๋ฒ„์ „์—์„œ๋Š” `a: Optional[str] = None` ๋Œ€์‹ ์— `a: str = None` ๋ฅผ ์„ ํ˜ธํ–ˆ์ง€๋งŒ ์ง€๊ธˆ์€ ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- ์•”์‹œ์ ์ธ ๋Œ€์‹  ๋ช…์‹œ์ ์ธ `X | None`์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์ด์ „ ๋ฒ„์ „์˜ PEP 484์—์„œ๋Š” `a: str = None`์„ `a: str | None = None`์œผ๋กœ ํ•ด์„ํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ, ์ด์ œ๋Š” ์ด๊ฒƒ์ด ์„ ํ˜ธ๋˜๋Š” ๋™์ž‘์ด ์•„๋‹™๋‹ˆ๋‹ค. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - def func(a: Optional[str], b: Optional[str] = None) -> str: - ... - def multiple_nullable_union(a: Union[None, str, int]) -> str: - ... + def modern_or_union(a: str | int | None, b: str | None = None) -> str: + ... + def union_optional(a: Union[str, int, None], b: Optional[str] = None) -> str: + ... ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ @@ -180,14 +213,13 @@ class MyClass: - ์–ด๋ ค์šด Type์„ ๋ณ„์นญ์œผ๋กœ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณ„์นญ์€ CapWorded์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ณ„์นญ์ด ์ด ๋ชจ๋“ˆ์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” \_Private์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์˜ˆ๋ฅผ ๋“ค์–ด Type๊ณผ ํ•จ๊ป˜ ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์ด ๋„ˆ๋ฌด ๊ธด ๊ฒฝ์šฐ +- TypeAlias ์ฃผ์„์€ ๋ฒ„์ „ 3.10 ์ด์ƒ์—์„œ๋งŒ ์ง€์›๋œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. - ```python - _ShortName = module_with_long_name.TypeWithLongName - ComplexMap = Mapping[str, List[Tuple[int, int]]] - ``` - -- ๋‹ค๋ฅธ ์˜ˆ๋กœ๋Š” ๋ณต์žกํ•œ ์ค‘์ฒฉ ์œ ํ˜•๊ณผ ํ•จ์ˆ˜์˜ ๋ณต์ˆ˜ ๋ฐ˜ํ™˜ ๋ณ€์ˆ˜(ํŠœํ”Œ)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. +```python +from typing import TypeAlias +_LossAndGradient: TypeAlias = tuple[tf.Tensor, tf.Tensor] +ComplexTFMap: TypeAlias = Mapping[str, _LossAndGradient] +``` @@ -207,11 +239,21 @@ class MyClass: #### 3.19.8 ๋‚ด๋ถ€ ๋ณ€์ˆ˜ ์ž‘์„ฑ -- ๋‚ด๋ถ€ ๋ณ€์ˆ˜๊ฐ€ ์œ ์ถ”ํ•˜๊ธฐ ์–ด๋ ต๊ฑฐ๋‚˜ ๋ถˆ๊ฐ€๋Šฅํ•œ ํƒ€์ž…์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ„๋„์˜ ์ฃผ์„์œผ๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + -```python -a = SomeUndecoratedFunction() # type: Foo -``` +- [_Annotated Assignments_](#annotated-assignments): ๋‚ด๋ถ€ ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์ถ”๋ก ํ•˜๊ธฐ ์–ด๋ ต๊ฑฐ๋‚˜ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ, ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ํ• ๋‹น์œผ๋กœ ํƒ€์ž…์„ ๋ช…์‹œํ•˜์„ธ์š”. ๋ณ€์ˆ˜ ์ด๋ฆ„๊ณผ ๊ฐ’ ์‚ฌ์ด์— ์ฝœ๋ก ๊ณผ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค (๊ธฐ๋ณธ๊ฐ’์ด ์žˆ๋Š” ํ•จ์ˆ˜ ์ธ์ˆ˜์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ). + + ```python + a: Foo = SomeUndecoratedFunction() + ``` + + + +- [_Type Comments_](#type-comments): ์ฝ”๋“œ๋ฒ ์ด์Šค์— ์—ฌ์ „ํžˆ ๋‚จ์•„ ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ (Python 3.6 ์ด์ „์—๋Š” ํ•„์š”ํ–ˆ์Œ), ๋” ์ด์ƒ `# type: ` ์ฃผ์„์„ ์ค„ ๋์— ์ถ”๊ฐ€ํ•˜์ง€ ๋งˆ์„ธ์š”. + + ```python + a = SomeUndecoratedFunction() # type: Foo + ``` @@ -223,30 +265,38 @@ a = SomeUndecoratedFunction() # type: Foo - ๋ฆฌ์ŠคํŠธ๋Š” ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. ```python -a = [1, 2, 3] # type: List[int] -b = (1, 2, 3) # type: Tuple[int, ...] -c = (1, "2", 3.5) # type: Tuple[int, str, float] +a: list[int] = [1, 2, 3] +b: tuple[int, ...] = (1, 2, 3) +c: tuple[int, str, float] = (1, "2", 3.5) ``` + -#### 3.19.10 TypeVar +#### 3.19.10 Type variables - ํŒŒ์ด์ฌํ˜• ์‹œ์Šคํ…œ์€ ์ผ๋ฐ˜์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ณต์žฅ ๊ธฐ๋Šฅ์ธ TypeVar๋Š” ํ”ํžˆ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. -- ํŒŒ์ด์„  Type์—๋Š” [generics](https://www.python.org/dev/peps/pep-0484/#generics)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. -- factory function `TypeVar`๋Š” ํ”ํžˆ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. +- ํŒŒ์ด์„  Type์—๋Š” [generics](https://peps.python.org/pep-0484/#generics)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. +- `TypeVar`์™€ `ParamSpec`๊ณผ ๊ฐ™์€ ํƒ€์ž… ๋ณ€์ˆ˜๋Š” ์ œ๋„ˆ๋ฆญ์„ ์‚ฌ์šฉํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ```python - from typing import List, TypeVar - T = TypeVar("T") + from collections.abc import Callable + from typing import ParamSpec, TypeVar + _P = ParamSpec("_P") + _T = TypeVar("_T") ... - def next(l: List[T]) -> T: - return l.pop() + def next(l: list[_T]) -> _T: + return l.pop() + def print_when_called(f: Callable[_P, _T]) -> Callable[_P, _T]: + def inner(*args: _P.args, **kwargs: _P.kwargs) -> _T: + print("Function was called") + return f(*args, **kwargs) + return inner ``` -- TypeVar๋Š” ๋ถ€์ž์—ฐ์Šค๋Ÿฌ์šธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +- `TypeVar`๋Š” ๋ถ€์ž์—ฐ์Šค๋Ÿฌ์šธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ```python AddableType = TypeVar("AddableType", int, float, str) @@ -254,7 +304,7 @@ c = (1, "2", 3.5) # type: Tuple[int, str, float] return a + b ``` -- `typing` ๋ชจ๋“ˆ์˜ ํ”ํžˆ ๋ฏธ๋ฆฌ ์ •์˜๋œ Type ๋ณ€์ˆ˜๋Š” `AnyStr`์ž…๋‹ˆ๋‹ค. `bytes`, `unicode`์ผ ์ˆ˜ ์žˆ๊ณ  ๋ชจ๋‘ ๊ฐ™์€ Type์ด์–ด์•ผ ํ•˜๋Š” ์—ฌ๋Ÿฌ ์ฃผ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +- `typing` ๋ชจ๋“ˆ์˜ ํ”ํžˆ ๋ฏธ๋ฆฌ ์ •์˜๋œ Type ๋ณ€์ˆ˜๋Š” `AnyStr`์ž…๋‹ˆ๋‹ค. `bytes`, `str`์ผ ์ˆ˜ ์žˆ๊ณ  ๋ชจ๋‘ ๊ฐ™์€ Type์ด์–ด์•ผ ํ•˜๋Š” ์—ฌ๋Ÿฌ ์ฃผ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ```python from typing import AnyStr @@ -264,48 +314,46 @@ c = (1, "2", 3.5) # type: Tuple[int, str, float] raise ValueError() ``` - - +- ํƒ€์ž… ๋ณ€์ˆ˜๋Š” ์„ค๋ช…์ ์ธ ์ด๋ฆ„์„ ๊ฐ€์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ, ๋‹ค์Œ ๋ชจ๋“  ๊ธฐ์ค€์„ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์˜ˆ์™ธ์ž…๋‹ˆ๋‹ค. -#### 3.19.11 ๋ฌธ์ž์—ด Type + - ์™ธ๋ถ€์—์„œ ๋ณด์ด์ง€ ์•Š๋Š” ๊ฒฝ์šฐ + - ์ œ์•ฝ ์กฐ๊ฑด์ด ์—†๋Š” ๊ฒฝ์šฐ -- String ์ฃผ์„์— ๋Œ€ํ•œ ์ ์ ˆํ•œ Type์€ ์ฝ”๋“œ์˜ ์šฉ๋„์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ -- `str`์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜์ง€๋งŒ `Text`๋„ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ `bytes`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ(Python 2์—์„œ๋Š” `str` ๋˜๋Š” `unicode`, Python3์—์„œ๋Š” `str`)๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” Python 2 ํ˜ธํ™˜ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ `Text`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + ```python + _T = TypeVar("_T") + _P = ParamSpec("_P") + AddableType = TypeVar("AddableType", int, float, str) + AnyFunction = TypeVar("AnyFunction", bound=Callable) + ``` -```python -def deals_with_text_data_in_py3(x: str) -> str: - ... -def deals_with_binary_data(x: bytes) -> bytes: - ... -def py2_compatible_text_data_processor(x: Text) -> Text: - ... -``` + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ -- ์ผ๋ถ€ ํ”ํ•˜์ง€ ์•Š์€ Python2 ํ˜ธํ™˜์„ฑ ์‚ฌ๋ก€์—์„œ๋Š” `Text` ๋Œ€์‹  `str`์ด ์˜๋ฏธ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ Python2์™€ Python3 ๊ฐ„์— ๋ฐ˜ํ™˜ ์œ ํ˜•์ด ๋™์ผํ•˜์ง€ ์•Š์„ ๋•Œ ํ˜ธํ™˜์„ฑ์„ ๋•๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. -- Python3์—๋Š” `unicode`๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ ˆ๋Œ€ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. -- ์ด๋Ÿฌํ•œ ๋ถˆ์ผ์น˜๊ฐ€ ์กด์žฌํ•˜๋Š” ์ด์œ ๋Š” `str`์ด Python3์™€ Python2์—์„œ ๋‹ค๋ฅธ ์˜๋ฏธ๋ฅผ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + ```python + T = TypeVar("T") + P = ParamSpec("P") + _T = TypeVar("_T", int, float, str) + _F = TypeVar("_F", bound=Callable) + ``` -- ๋ถ€์ ์ ˆํ•œ ์˜ˆ + + + + -```python -def py2_code(x: str) -> unicode: - ... -``` +#### 3.19.11 ๋ฌธ์ž์—ด Type -If the type can be either bytes or text, use `Union`, with the appropriate text -type. +> ์ƒˆ๋กœ์šด ์ฝ”๋“œ์—์„œ๋Š” `typing.Text`๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. ์ด๋Š” Python 2/3 ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. -```python -from typing import Text, Union -... -def py3_only(x: Union[bytes, str]) -> Union[bytes, str]: - ... -def py2_compatible(x: Union[bytes, Text]) -> Union[bytes, Text]: - ... -``` +- ๋ฌธ์ž์—ด/ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์—๋Š” `str`์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ด์ง„ ๋ฐ์ดํ„ฐ์™€ ๊ด€๋ จ๋œ ์ฝ”๋“œ์—์„œ๋Š” `bytes`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + + ```python + def deals_with_text_data(x: str) -> str: + ... + def deals_with_binary_data(x: bytes) -> bytes: + ... + ``` - ํ•จ์ˆ˜์˜ ๋ชจ๋“  string Type์ด ํ•ญ์ƒ ๋™์ผํ•œ ๊ฒฝ์šฐ(์˜ˆ, ๋ฐ˜ํ™˜ Type์ด ์œ„์˜ ์ฝ”๋“œ์—์„œ ์ธ์ž Type๊ณผ ๋™์ผํ•œ ๊ฒฝ์šฐ) [AnyStr](#s3.19.10-type-var)๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -316,19 +364,31 @@ def py2_compatible(x: Union[bytes, Text]) -> Union[bytes, Text]: #### 3.19.12 Typing ์ถ”๊ฐ€ -- `typing` ๋ชจ๋“ˆ์˜ ํด๋ž˜์Šค๋Š” ํ•ญ์ƒ ํด๋ž˜์Šค ์ž์ฒด๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. `typing` ๋ชจ๋“ˆ์—์„œ ํ•œ ์ค„์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ํŠน์ • ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- `typing` ๋˜๋Š” `collections.abc` ๋ชจ๋“ˆ์—์„œ ์ •์  ๋ถ„์„ ๋ฐ ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ์‹ฌ๋ณผ(ํƒ€์ž…, ํ•จ์ˆ˜, ์ƒ์ˆ˜ ๋“ฑ)์€ ํ•ญ์ƒ ์‹ฌ๋ณผ ์ž์ฒด๋ฅผ ์ž„ํฌํŠธํ•˜์„ธ์š”. +- ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ผ๋ฐ˜์ ์ธ ์ฃผ์„์ด ๋” ๊ฐ„๊ฒฐํ•ด์ง€๊ณ , ์ „ ์„ธ๊ณ„์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํƒ€์ž… ์ฃผ์„ ๊ด€ํ–‰์— ๋งž์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- `typing` ๋ฐ `collections.abc` ๋ชจ๋“ˆ์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŠน์ • ์‹ฌ๋ณผ์„ ํ•œ ์ค„์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ž„ํฌํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python - from typing import Any, Dict, Optional + from collections.abc import Mapping, Sequence + from typing import Any, Generic, cast, TYPE_CHECKING ``` -- `typing`์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์ด ๋กœ์ปฌ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•œ๋‹ค๋Š” ์ ์—์„œ, `typing`์˜ ๋ชจ๋“  ์ด๋ฆ„์€ ํ‚ค์›Œ๋“œ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ทจ๊ธ‰๋˜์–ด์•ผ ํ•˜๋ฉฐ, typing์ด๋“  ์•„๋‹ˆ๋“  Python ์ฝ”๋“œ์— ์ •์˜๋˜์–ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค. -- ๋ชจ๋“ˆ์— ์žˆ๋Š” Type๊ณผ ๊ธฐ์กด ์ด๋ฆ„์ด ์ถฉ๋Œํ•˜๋Š” ๊ฒฝ์šฐ `import x as y`๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์ด ๋ฐฉ์‹์œผ๋กœ ์ž„ํฌํŠธํ•˜๋ฉด ๋กœ์ปฌ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ํ•ญ๋ชฉ์ด ์ถ”๊ฐ€๋˜๋ฏ€๋กœ, `typing` ๋˜๋Š” `collections.abc`์˜ ์ด๋ฆ„์€ ํ‚ค์›Œ๋“œ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ทจ๊ธ‰๋˜์–ด์•ผ ํ•˜๋ฉฐ, Python ์ฝ”๋“œ์—์„œ ์ •์˜๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์ž… ์—ฌ๋ถ€์™€ ๊ด€๊ณ„์—†์ด ๋ง์ž…๋‹ˆ๋‹ค. +- ๋ชจ๋“ˆ ๋‚ด์—์„œ ํƒ€์ž…๊ณผ ๊ธฐ์กด ์ด๋ฆ„ ๊ฐ„์— ์ถฉ๋Œ์ด ์žˆ๋Š” ๊ฒฝ์šฐ, `import x as y`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž„ํฌํŠธํ•˜์„ธ์š”. ```python from typing import Any as AnyType ``` +- ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ, ์ฃผ์„์œผ๋กœ ๋‚ด์žฅ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. +- Prefer to use built-in types as annotations where available. +- Python์€ [PEP-585](https://peps.python.org/pep-0585/)๋ฅผ ํ†ตํ•ด ๋งค๊ฐœํ˜• ์ปจํ…Œ์ด๋„ˆ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ ํƒ€์ž… ์ฃผ์„์„ ์ง€์›ํ•˜๋ฉฐ, ์ด๋Š” Python 3.9์—์„œ ๋„์ž…๋˜์—ˆ์Šต๋‹ˆ๋‹ค. + + ```python + def generate_foo_scores(foo: set[str]) -> list[float]: + ... + ``` + @@ -369,7 +429,7 @@ def f(x: "sketch.Sketch"): ... - ํ•˜์ง€๋งŒ ๊ธฐ์ˆ ์ ์œผ๋กœ Circular ์ข…์†์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๋‹ค์–‘ํ•œ ๋นŒ๋“œ ์‹œ์Šคํ…œ์€ ๋‹ค๋ฅธ ๋ชจ๋“ˆ์— ์˜์กดํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ ‡๊ฒŒ ํ•˜๋„๋ก ํ—ˆ๋ฝํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. - Circular ์ข…์†์„ ์ƒ์„ฑํ•˜๋Š” ๋ชจ๋“ˆ์„ `Any`๋กœ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค. - - ์˜๋ฏธ์žˆ๋Š” ์ด๋ฆ„์œผ๋กœ [alias](#s3.19.6-aliases)๋ฅผ ์ง€์ •ํ•˜๊ณ  ๋ชจ๋“ˆ์˜ ์‹ค์ œ Type ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์„ธ์š” (์–ด๋–ค ๊ฒƒ์˜ ์–ด๋–ค ์†์„ฑ์ธ Any). + - ์˜๋ฏธ์žˆ๋Š” ์ด๋ฆ„์œผ๋กœ [alias](#s3.19.6-aliases)๋ฅผ ์ง€์ •ํ•˜๊ณ  ๋ชจ๋“ˆ์˜ ์‹ค์ œ Type ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์„ธ์š” (`Any`์˜ ๋ชจ๋“  ์†์„ฑ์€ `Any`์ž…๋‹ˆ๋‹ค.). - Alias์˜ ์ •์˜๋Š” ๋งˆ์ง€๋ง‰์œผ๋กœ import์™€ ํ•œ ์ค„๋กœ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ```python @@ -386,31 +446,35 @@ def my_method(self, var: "some_mod.SomeType") -> None: #### 3.19.15 ์ผ๋ฐ˜ -- ์ฃผ์„์„ ๋‹ฌ๋•Œ, ์ผ๋ฐ˜ Type๋ฅผ ์ง€์ •ํ•˜๊ธฐ๋ฅผ ์„ ํ˜ธํ•˜๋ฉฐ ๊ทธ๋ ‡์ง€ [์•Š์„ ๋•Œ์—๋Š” `Any`๋กœ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค](https://www.python.org/dev/peps/pep-0484/#the-any-type). +- ์ฃผ์„์„ ๋‹ฌ๋•Œ, ์ผ๋ฐ˜ Type๋ฅผ ์ง€์ •ํ•˜๊ธฐ๋ฅผ ์„ ํ˜ธํ•˜๋ฉฐ ๊ทธ๋ ‡์ง€ [์•Š์„ ๋•Œ์—๋Š” `Any`๋กœ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค](https://peps.python.org/pep-0484/#the-any-type). -```python -def get_names(employee_ids: List[int]) -> Dict[int, Any]: - ... -``` + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ -```python -# ๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜ ๋ชจ๋‘ get_names(employee_ids: List[Any]) -> Dict[Any, Any] -def get_names(employee_ids: list) -> Dict: - ... + ```python + def get_names(employee_ids: Sequence[int]) -> Mapping[int, str]: + ... + ``` -def get_names(employee_ids: List) -> Dict: - ... -``` + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ + + ```python + # ์ด๋Š” get_names(employee_ids: Sequence[Any]) -> Mapping[Any, Any]๋กœ ํ•ด์„๋ฉ๋‹ˆ๋‹ค. + def get_names(employee_ids: Sequence) -> Mapping: + ``` - ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ ํ•ฉํ•œ Type์ด `Any`์ผ ๋•Œ, ๋ช…์‹œ์ ์œผ๋กœ ํ‘œํ˜„๋˜๋ฉฐ, ๋งŽ์€ ๊ฒฝ์šฐ์— [`TypeVar`](#s3.19.10-type-var)๊ฐ€ ๋” ์ ํ•ฉํ•  ์ˆ˜ ์žˆ์Œ์„ ๊ธฐ์–ตํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. -```python -def get_names(employee_ids: List[Any]) -> Dict[Any, str]: - """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" -``` + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ -```python -T = TypeVar('T') -def get_names(employee_ids: List[T]) -> Dict[T, str]: - """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" -``` + ```python + def get_names(employee_ids: Sequence[Any]) -> Mapping[Any, str]: + """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" + ``` + + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ + + ```python + _T = TypeVar('_T') + def get_names(employee_ids: Sequence[_T]) -> Mapping[_T, str]: + """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" + ``` diff --git "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.2 \354\244\204 \352\270\270\354\235\264.md" "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.2 \354\244\204 \352\270\270\354\235\264.md" index b359776..d43bf1c 100644 --- "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.2 \354\244\204 \352\270\270\354\235\264.md" +++ "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.2 \354\244\204 \352\270\270\354\235\264.md" @@ -10,10 +10,10 @@ - ๊ฒฝ๋กœ์ด๋ฆ„์ด๋‚˜ URLs์™€ ๊ฐ™์€ ๊ณต๋ฐฑ์„ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ๊ธด ๋ชจ๋“ˆ์ˆ˜์ค€ ๋ฌธ์ž์ƒ์ˆ˜๋Š” ์—ฌ๋Ÿฌ ์ค„์— ๋‚˜๋ˆ„์–ด ๊ธฐ๋กํ•˜๊ธฐ ๋ถˆํŽธํ•  ๊ฒฝ์šฐ - Pylint ๋น„ํ™œ์„ฑํ™” ์ฃผ์„๋ฌธ (e.g.: `# pylint: disable=invalid-name`) -- 3๊ฐœ ์ด์ƒ์˜ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €๋ฅผ ์š”๊ตฌํ•˜๋Š” `with` ๊ตฌ๋ฌธ์„ ์ œ์™ธํ•˜๊ณ  ๋ฐฑ์Šฌ๋ž˜์‰ฌ(`\`) ๋ฅผ ์ด์šฉํ•œ ๋ฌธ์žฅ์—ฐ์žฅ์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. - -- Python์˜ [์†Œ/์ค‘/๋Œ€ ๊ด„ํ˜ธ ๋‚ด๋ถ€์˜ ๋ฌต์‹œ์  ๋ผ์ธ๊ฒฐํ•ฉ](http://docs.python.org/reference/lexical_analysis.html#implicit-line-joining)์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- [๋ช…์‹œ์ ์ธ ์ค„ ์—ฐ์†](https://docs.python.org/3/reference/lexical_analysis.html#explicit-line-joining)์„ ์œ„ํ•ด ๋ฐฑ์Šฌ๋ž˜์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. +- ๋Œ€์‹ ์— Python์˜ [์†Œ/์ค‘/๋Œ€ ๊ด„ํ˜ธ ๋‚ด๋ถ€์˜ ๋ฌต์‹œ์  ๋ผ์ธ๊ฒฐํ•ฉ](http://docs.python.org/reference/lexical_analysis.html#implicit-line-joining)์„ ์‚ฌ์šฉํ•˜์„ธ์š”. - ํ•„์š”ํ•˜๋‹ค๋ฉด, ๊ตฌ๋ฌธ ์–‘์ชฝ์— ์ถ”๊ฐ€๋กœ ๊ด„ํ˜ธ๋ฅผ ๋”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- ์ด ๊ทœ์น™์€ ๋ฌธ์ž์—ด ๋‚ด์—์„œ ๋ฐฑ์Šฌ๋ž˜์‹œ๋กœ ์ด์Šค์ผ€์ดํ”„๋œ ๊ฐœํ–‰์„ ๊ธˆ์ง€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์•„๋ž˜ [์ฐธ์กฐ](#strings)). - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -21,8 +21,29 @@ foo_bar(self, width, height, color='black', design=None, x='foo', emphasis=None, highlight=0) - if (width == 0 and height == 0 and - color == 'red' and emphasis == 'strong'): + if (width == 0 and height == 0 and + color == 'red' and emphasis == 'strong'): + (bridge_questions.clarification_on + .average_airspeed_of.unladen_swallow) = 'African or European?' + with ( + very_long_first_expression_function() as spam, + very_long_second_expression_function() as beans, + third_thing() as eggs, + ): + place_order(eggs, beans, spam, beans) + ``` + + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ + + ```python + if width == 0 and height == 0 and \ + color == 'red' and emphasis == 'strong': + bridge_questions.clarification_on \ + .average_airspeed_of.unladen_swallow = 'African or European?' + with very_long_first_expression_function() as spam, \ + very_long_second_expression_function() as beans, \ + third_thing() as eggs: + place_order(eggs, beans, spam, beans) ``` - ๋งŒ์•ฝ ๋ฆฌํ„ฐ๋Ÿด ๋ฌธ์ž์—ด์„ ํ•œ ์ค„์— ํ‘œํ˜„ํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ด„ํ˜ธ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฌต์‹œ์  ๋ผ์ธ๊ฒฐํ•ฉ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -32,53 +53,51 @@ 'long long long long long long string') ``` -- ์ฃผ์„์˜ ๊ฒฝ์šฐ ๊ธด URLs ๋“ค์€ ํ•œ์ค„์— ํ‘œํ˜„ํ•˜์„ธ์š”. +- ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ๋†’์€ ๊ตฌ๋ฌธ ์ˆ˜์ค€์—์„œ ์ค„์„ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜์„ธ์š”. ์ค„์„ ๋‘ ๋ฒˆ ๋‚˜๋ˆ ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ, ๋‘ ๋ฒˆ ๋ชจ๋‘ ๋™์ผํ•œ ๊ตฌ๋ฌธ ์ˆ˜์ค€์—์„œ ๋‚˜๋ˆ„์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - # See details at - # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html + bridgekeeper.answer( + name="Arthur", quest=questlib.find(owner="Arthur", perilous=True)) + answer = (a_long_line().of_chained_methods() + .that_eventually_provides().an_answer()) + if ( + config is None + or 'editor.language' not in config + or config['editor.language'].use_spaces is False + ): + use_tabs() ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - # See details at - # http://www.example.com/us/developer/documentation/api/content/\ - # v2.0/csv_file_name_extension_full_specification.html + bridgekeeper.answer(name="Arthur", quest=questlib.find( + owner="Arthur", perilous=True)) + answer = a_long_line().of_chained_methods().that_eventually_provides( + ).an_answer() + if (config is None or 'editor.language' not in config or config[ + 'editor.language'].use_spaces is False): + use_tabs() ``` -- 3์ค„ ์ด์ƒ์ด ํ•„์š”ํ•œ `with` ๊ตฌ๋ฌธ์„ ์ •์˜ํ•  ๋•Œ๋Š” ๋ฐฑ์Šฌ๋ž˜์‰ฌ(`\`) ๋ฅผ ์ด์šฉํ•œ ๋ฌธ์žฅ์—ฐ์žฅ์ด ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. 2์ค„์ธ ๊ฒฝ์šฐ ๋„ค์Šคํ‹ฐ๋“œ `with`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š” +- ์ฃผ์„์˜ ๊ฒฝ์šฐ ๊ธด URLs ๋“ค์€ ํ•œ์ค„์— ํ‘œํ˜„ํ•˜์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - with very_long_first_expression_function() as spam, \ - very_long_second_expression_function() as beans, \ - third_thing() as eggs: - place_order(eggs, beans, spam, beans) + # See details at + # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - with VeryLongFirstExpressionFunction() as spam, \ - VeryLongSecondExpressionFunction() as beans: - PlaceOrder(beans, spam) - ``` - - - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ - - ```python - with very_long_first_expression_function() as spam: - with very_long_second_expression_function() as beans: - place_order(beans, spam) + # See details at + # http://www.example.com/us/developer/documentation/api/content/\ + # v2.0/csv_file_name_extension_full_specification.html ``` - ์œ„์˜ ์˜ˆ์‹œ์—์„œ ๊ฐ ์š”์†Œ์— ์‚ฌ์šฉ๋œ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์ž˜ ๊ธฐ์–ตํ•˜์„ธ์š”. ๋” ์ž์„ธํ•œ ์ •๋ณด๋Š” [๋“ค์—ฌ์“ฐ๊ธฐ](#s3.4-indentation) ์ฑ•ํ„ฐ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. - -์œ„์—์„œ ์–ธ๊ธ‰๋˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ ํ•œ ์ค„์˜ ๊ธธ์ด๊ฐ€ 80์ž๋ฅผ ์ดˆ๊ณผํ•จ์—๋„ -[yapf](https://github.com/google/yapf/) -์˜คํ† ํฌ๋ฉ”ํ„ฐ๊ฐ€ ๋ณ„๋‹ค๋ฅธ ๋„์›€์„ ์ฃผ์ง€ ๋ชปํ•œ๋‹ค๋ฉด 80์ž ์ด์ƒ ์ดˆ๊ณผ๊ฐ€ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. -์ž‘์„ฑ์ž๋Š” ์ƒ์‹์ ์ธ ์ˆ˜์ค€๋‚ด์—์„œ ์œ„ ๋ฌธ์„œ์˜ ์‚ฌํ•ญ์„ ์ฐธ๊ณ ํ•˜์—ฌ ์ค„์„ ๋ถ„๋ฆฌํ•˜๋Š”๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•ฉ๋‹ˆ๋‹ค. \ No newline at end of file +- ์œ„์—์„œ ์–ธ๊ธ‰๋˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ ํ•œ ์ค„์˜ ๊ธธ์ด๊ฐ€ 80์ž๋ฅผ ์ดˆ๊ณผํ•จ์—๋„ [Black](https://github.com/psf/black) ํ˜น์€ [Pyink](https://github.com/google/pyink) ์˜คํ† ํฌ๋ฉ”ํ„ฐ๊ฐ€ ๋ณ„๋‹ค๋ฅธ ๋„์›€์„ ์ฃผ์ง€ ๋ชปํ•œ๋‹ค๋ฉด 80์ž ์ด์ƒ ์ดˆ๊ณผ๊ฐ€ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ž‘์„ฑ์ž๋Š” ์ƒ์‹์ ์ธ ์ˆ˜์ค€๋‚ด์—์„œ ์œ„ ๋ฌธ์„œ์˜ ์‚ฌํ•ญ์„ ์ฐธ๊ณ ํ•˜์—ฌ ์ค„์„ ๋ถ„๋ฆฌํ•˜๋Š”๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•ฉ๋‹ˆ๋‹ค. diff --git "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.4 \353\223\244\354\227\254\354\223\260\352\270\260.md" "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.4 \353\223\244\354\227\254\354\223\260\352\270\260.md" index bacd85f..e2bed6c 100644 --- "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.4 \353\223\244\354\227\254\354\223\260\352\270\260.md" +++ "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.4 \353\223\244\354\227\254\354\223\260\352\270\260.md" @@ -4,26 +4,26 @@ - ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ _4 ์นธ_ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ํ•˜์„ธ์š”. -- ํƒญ์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํƒญ๊ณผ ์ŠคํŽ˜์ด์Šค๋ฅผ ์„ž์–ด์„œ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. -- ๋ฌต์‹œ์  ๋ฌธ์žฅ์—ฐ์žฅ์˜ ๊ฒฝ์šฐ [line length](#s3.2-line-length) ์„น์…˜์˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ๋™์ผํ•œ ๋ฌธ์žฅ์— ํฌํ•จ๋œ ์š”์†Œ๋“ค์„ ์ˆ˜์ง์ •๋ ฌํ•˜๊ฑฐ๋‚˜ ์ฒซ ์—ด๋ฆฐ๊ด„ํ˜ธ ์ดํ›„๋กœ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†๋Š” 4 ์นธ hanging indent ๋ฅผ ์ ์šฉํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ํƒญ์„ ์ ˆ๋Œ€ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. ์•”์‹œ๋œ ์ค„ ์—ฐ์†์€ ๋ž˜ํ•‘๋œ ์š”์†Œ๋ฅผ ์ˆ˜์ง์œผ๋กœ ์ •๋ ฌํ•ด์•ผ ํ•˜๋ฉฐ([์ค„ ๊ธธ์ด ์˜ˆ์ œ](#s3.2-line-length) ์ฐธ์กฐ), ๋˜๋Š” 4๊ฐœ์˜ ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ–‰์„ ๋“ค์—ฌ์“ฐ๊ธฐ ํ•˜์„ธ์š”. +- ๋‹ซ๋Š” ๊ด„ํ˜ธ(์›, ๋Œ€๊ฐ์„  ๋˜๋Š” ์ค‘๊ด„ํ˜ธ)๋Š” ํ‘œํ˜„์‹์˜ ๋์— ๋ฐฐ์น˜ํ•˜๊ฑฐ๋‚˜ ๋ณ„๋„์˜ ์ค„์— ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด ๊ฒฝ์šฐ ํ•ด๋‹น ์—ฌ๋Š” ๊ด„ํ˜ธ์™€ ๊ฐ™์€ ์ค„์— ๋“ค์—ฌ์“ฐ๊ธฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - # Aligned with opening delimiter + # ์—ฌ๋Š” ๊ตฌ๋ถ„ ๊ธฐํ˜ธ์™€ ์ •๋ ฌ๋จ foo = long_function_name(var_one, var_two, var_three, var_four) meal = (spam, beans) - # Aligned with opening delimiter in a dictionary + # ๋”•์…”๋„ˆ๋ฆฌ์˜ ์—ฌ๋Š” ๊ตฌ๋ถ„ ๊ธฐํ˜ธ์™€ ์ •๋ ฌ๋จ foo = { 'long_dictionary_key': value1 + value2, ... } - # 4-space hanging indent; nothing on first line + # 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ, ์ฒซ ๋ฒˆ์งธ ์ค„์—๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†์Œ foo = long_function_name( var_one, var_two, var_three, var_four) @@ -31,7 +31,16 @@ spam, beans) - # 4-space hanging indent in a dictionary + # 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ; ์ฒซ ๋ฒˆ์งธ ์ค„์—๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†์Œ, ๋‹ซ๋Š” ๊ด„ํ˜ธ๋Š” ์ƒˆ ์ค„์— ๋ฐฐ์น˜ + foo = long_function_name( + var_one, var_two, var_three, + var_four + ) + meal = ( + spam, + beans, + ) + # ๋”•์…”๋„ˆ๋ฆฌ์—์„œ 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ foo = { 'long_dictionary_key': long_dictionary_value, @@ -42,18 +51,18 @@ - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - # Stuff on first line forbidden + # ์ฒซ ๋ฒˆ์งธ ์ค„์— ๋‚ด์šฉ์ด ์žˆ์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. foo = long_function_name(var_one, var_two, var_three, var_four) meal = (spam, beans) - # 2-space hanging indent forbidden + # 2์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ๋Š” ๊ธˆ์ง€๋ฉ๋‹ˆ๋‹ค. foo = long_function_name( var_one, var_two, var_three, var_four) - # No hanging indent in a dictionary + # ๋”•์…”๋„ˆ๋ฆฌ์—์„œ๋Š” ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. foo = { 'long_dictionary_key': long_dictionary_value, @@ -65,8 +74,8 @@ #### 3.4.1 ์›์†Œ ๋‚˜์—ด ์‹œ ํ›„ํ–‰ ์‰ผํ‘œ -- ์—ฌ๋Ÿฌ ์›์†Œ๋ฅผ ๋‚˜์—ดํ•  ๋•Œ ํ›„ํ–‰ ์‰ผํ‘œ๋Š” `]`, `)`, `}` ์™€ ๊ฐ™์ด ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋‹ซ๋Š” ํ† ํฐ์ด ๋งˆ์ง€๋ง‰ ์›์†Œ์™€ ๊ฐ™์€ ์ค„์— ์žˆ์ง€ ์•Š์„ ๋•Œ๋งŒ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. -- ๋˜ํ•œ ํ›„ํ–‰ ์‰ผํ‘œ์˜ ์กด์žฌ ์—ฌ๋ถ€๋Š” ํŒŒ์ด์ฌ ์ฝ”๋“œ ์˜คํ† -ํฌ๋ฉ”ํ„ฐ [YAPF](https://pypi.org/project/yapf/) ๊ฐ€ ์ปจํ…Œ์ด๋„ˆ์˜ ์›์†Œ๋ฅผ ํ•œ ์ค„์— ํ•˜๋‚˜์”ฉ `,` ๊ธฐํ˜ธ๋ฅผ ๋ถ™์—ฌ ์ž๋™ ์ •๋ ฌํ•˜๋„๋ก ์ง€์‹œํ•˜๋Š” ํžŒํŠธ๋กœ๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. +- ํ›„ํ–‰ ์‰ผํ‘œ๋Š” ์‹œํ€€์Šค์˜ ์š”์†Œ์—์„œ ๋‹ซ๋Š” ๊ตฌ๋ฌธ ๊ธฐํ˜ธ `]`, `)`, ๋˜๋Š” `}`๊ฐ€ ๋งˆ์ง€๋ง‰ ์š”์†Œ์™€ ๊ฐ™์€ ์ค„์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์™€ ๋‹จ์ผ ์š”์†Œ๋ฅผ ๊ฐ€์ง„ ํŠœํ”Œ์— ๋Œ€ํ•ด์„œ๋งŒ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. +- ํ›„ํ–‰ ์‰ผํ‘œ์˜ ์กด์žฌ๋Š” Python ์ฝ”๋“œ ์ž๋™ ํฌ๋งทํ„ฐ์ธ [Black](https://github.com/psf/black)์ด๋‚˜ [Pyink](https://github.com/google/pyink)์—๊ฒŒ ๋งˆ์ง€๋ง‰ ์š”์†Œ ๋’ค์— `,`๊ฐ€ ์žˆ์„ ๋•Œ ํ•ญ๋ชฉ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ•œ ์ค„์— ํ•˜๋‚˜์˜ ํ•ญ๋ชฉ์”ฉ ์ž๋™์œผ๋กœ ํฌ๋งทํ•˜๋„๋ก ์ง€์‹œํ•˜๋Š” ํžŒํŠธ๋กœ๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -87,6 +96,5 @@ 0, 1, 4, - 6 - ] + 6,] ``` diff --git "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.5 \353\271\210 \354\244\204.md" "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.5 \353\271\210 \354\244\204.md" index 7097185..47435be 100644 --- "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.5 \353\271\210 \354\244\204.md" +++ "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.5 \353\271\210 \354\244\204.md" @@ -3,7 +3,7 @@ ### 3.5 Blank Lines - ํ•จ์ˆ˜ ์„ ์–ธ์ด๋“  ๊ฐ์ฒด ์„ ์–ธ์ด๋“  ์ตœ์ƒ์œ„ ์„ ์–ธ๋ฌธ๊ณผ๋Š” 2๊ฐœ์˜ ๋นˆ ์ค„์„ ์‚ฌ์ด์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๊ฐ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ๋˜๋Š” `class` ์ค„๊ณผ ์ “ ๋ฒˆ์งธ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ์‹œ ๊ทธ ์‚ฌ์ด์—๋Š” ํ•œ ๊ฐœ์˜ ๋นˆ ์ค„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๊ฐ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ๋˜๋Š” `class`์˜ docstring ์ค„๊ณผ ์ “ ๋ฒˆ์งธ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ์‹œ ๊ทธ ์‚ฌ์ด์—๋Š” ํ•œ ๊ฐœ์˜ ๋นˆ ์ค„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - `def` ์ค„ ์ดํ›„์—๋Š” ๋นˆ ์ค„์ด ์—†์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ํ•จ์ˆ˜์™€ ๋ฉ”์†Œ๋“œ ์‚ฌ์ด์— ๊ฐœ๋ฐœ์ž์˜ ํŒ๋‹จํ•˜์— ์ ์ ˆํ•˜๊ฒŒ ํ•œ ๊ฐœ์˜ ๋นˆ ์ค„์„ ์‚ฌ์šฉํ•˜์„ธ์š”. diff --git "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.7 Shebang_Line.md" "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.7 Shebang_Line.md" index d8d5885..7f3e8db 100644 --- "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.7 Shebang_Line.md" +++ "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.7 Shebang_Line.md" @@ -3,7 +3,7 @@ ### 3.7 Shebang Line - ๋Œ€๋ถ€๋ถ„์˜ `.py` ํŒŒ์ผ์€ `#!` ๋กœ ์‹œ์ž‘ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. -- [PEP-394](https://www.python.org/dev/peps/pep-0394/)์— ๋”ฐ๋ผ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ฉ”์ธ ํŒŒ์ผ ์ฒซ ์ค„์— `#!/usr/bin/env python3` (virtualenvs ์ง€์›) ๋˜๋Š” `#!/usr/bin/python3`์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. +- [PEP-394](https://peps.python.org/pep-0394/)์— ๋”ฐ๋ผ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ฉ”์ธ ํŒŒ์ผ ์ฒซ ์ค„์— `#!/usr/bin/env python3` (virtualenvs ์ง€์›) ๋˜๋Š” `#!/usr/bin/python3`์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. - ์ด ์ค„์€ ํŒŒ์ด์ฌ ํŒŒ์ผ์„ import ํ• ๋•Œ๋Š” ๋ฌด์‹œ๋˜์ง€๋งŒ ์‹คํ–‰ ๋ ๋•Œ๋Š” ์ปค๋„์ด ์–ด๋–ค ํŒŒ์ด์ฌ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. - ๋”ฐ๋ผ์„œ ์ง์ ‘ ์‹คํ–‰๋  ํŒŒ์ผ์— ๊ธฐ๋กํ•˜๋Š”๊ฒƒ์ด ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. diff --git "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.8 \354\243\274\354\204\235\352\263\274 docstring.md" "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.8 \354\243\274\354\204\235\352\263\274 docstring.md" index 480875d..efb1916 100644 --- "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.8 \354\243\274\354\204\235\352\263\274 docstring.md" +++ "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/3.8 \354\243\274\354\204\235\352\263\274 docstring.md" @@ -11,7 +11,7 @@ - ํŒŒ์ด์ฌ์€ ์ฝ”๋“œ๋ฅผ ๋ฌธ์„œํ™” ํ•  ๋•Œ _docstring_ ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. - docstring ์€ ํŒจํ‚ค์ง€, ๋ชจ๋“ˆ, ํด๋ž˜์Šค๋‚˜ ํ•จ์ˆ˜์˜ ์ฒซ๋ฒˆ์งธ ์„ ์–ธ๋˜๋Š” ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. - ์ด ๋ฌธ์ž์—ด์€ `pydoc` ์ด ์‚ฌ์šฉํ•˜๋Š” `__doc__` ๋ฉค๋ฒ„ ์˜ค๋ธŒ์ ํŠธ์—์„œ ์ž๋™์œผ๋กœ ์ถ”์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์—ฌ๋Ÿฌ๋ถ„์˜ ๋ชจ๋“ˆ์—์„œ `pydoc` ๋ฅผ ์‹คํ–‰ ํ›„ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ณด์„ธ์š”) -- [PEP257](https://www.google.com/url?sa=D&q=http://www.python.org/dev/peps/pep-0257/) ์— ๋”ฐ๋ผ docstring ์„ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋๋‚ผ ๋•Œ๋Š” `"""` ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- [PEP257](https://peps.python.org/pep-0257/) ์— ๋”ฐ๋ผ docstring ์„ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋๋‚ผ ๋•Œ๋Š” `"""` ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. - docstring์€ ๋งˆ์นจํ‘œ, ๋ฌผ์Œํ‘œ, ๋Š๋‚Œํ‘œ๋กœ ๋๋‚˜๋Š” ์š”์•ฝ์ค„(ํ•œ ์ค„)๋กœ ์‹œ์ž‘ํ•˜์—ฌ์•ผ ํ•˜๋ฉฐ ํ•œ ์ค„์˜ ๊ณต๋ฐฑ์„ ๋‘๊ณ  ๋‚ด์šฉ์„ ๋‹ด๊ณ ์žˆ๋Š” ๋‚˜๋จธ์ง€ docstring ์ด ์ด์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ๋˜ํ•œ ๋‚ด์šฉ์„ ๋‹ด๊ณ ์žˆ๋Š” docstring ์€ `"""` ์™€ ๊ฐ™์€ ์ปค์„œ์œ„์น˜์—์„œ ์‹œ์ž‘ํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -19,36 +19,70 @@ #### 3.8.2 Modules -- ๋ชจ๋“  ํŒŒ์ผ์€ ๋ผ์ด์„ผ์Šค ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ํ”„๋กœ์ ํŠธ์— ์•Œ๋งž๋Š” ๋ผ์ด์„ผ์Šค ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ์„ ํƒํ•˜์„ธ์š”. (์˜ˆ๋ฅผ ๋“ค๋ฉด, Apache 2.0, BSD, LGPL, GPL) +- ๋ชจ๋“  ํŒŒ์ผ์€ ๋ผ์ด์„ผ์Šค ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + + ```python + """๋ชจ๋“ˆ์ด๋‚˜ ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•œ ํ•œ ์ค„ ์š”์•ฝ์œผ๋กœ, ๋งˆ์นจํ‘œ๋กœ ๋๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. + + ํ•œ ์ค„์„ ๋น„์›Œ๋‘์„ธ์š”. ์ด docstring์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์—๋Š” ๋ชจ๋“ˆ์ด๋‚˜ ํ”„๋กœ๊ทธ๋žจ์— + ๋Œ€ํ•œ ์ „๋ฐ˜์ ์ธ ์„ค๋ช…์ด ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์„ ํƒ์ ์œผ๋กœ, ๋‚ด๋ณด๋‚ธ ํด๋ž˜์Šค์™€ + ํ•จ์ˆ˜์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ์„ค๋ช… ๋ฐ/๋˜๋Š” ์‚ฌ์šฉ ์˜ˆ์‹œ๋„ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + ์ „ํ˜•์ ์ธ ์‚ฌ์šฉ ์˜ˆ์‹œ: + + foo = ClassFoo() + bar = foo.FunctionBar() + """ + ``` + + + + +##### 3.8.2.1 Test modules + +- ํ…Œ์ŠคํŠธ ํŒŒ์ผ์˜ ๋ชจ๋“ˆ ์ˆ˜์ค€ docstring์€ ํ•„์ˆ˜๋Š” ์•„๋‹™๋‹ˆ๋‹ค. +- ์ถ”๊ฐ€์ ์ธ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•  ํ•„์š”๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์˜ˆ๋ฅผ ๋“ค๋ฉด, ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ๋‚ด์šฉ, ํŠน์ดํ•œ ์„ค์ • ํŒจํ„ด์— ๋Œ€ํ•œ ์„ค๋ช…, ์™ธ๋ถ€ ํ™˜๊ฒฝ์— ๋Œ€ํ•œ ์˜์กด์„ฑ ๋“ฑ์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +"""์ด Blaze ํ…Œ์ŠคํŠธ๋Š” golden ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +`google3` ๋””๋ ‰ํ† ๋ฆฌ์—์„œ +`blaze run //foo/bar:foo_test -- --update_golden_files` ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜์—ฌ +์ด๋Ÿฌํ•œ ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +""" +``` + +- ์ƒˆ๋กœ์šด ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” docstring์€ ์‚ฌ์šฉํ•˜์ง€ ๋ง์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +```python +"""Tests for foo.bar.""" +``` #### 3.8.3 Functions and Methods -- ์ด ์„น์…˜์—์„œ "ํ•จ์ˆ˜"๋Š” ๋ฉ”์†Œ๋“œ, ํ•จ์ˆ˜ ๋˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. +- ์ด ์„น์…˜์—์„œ โ€˜functionโ€™์€ ๋ฉ”์†Œ๋“œ, ํ•จ์ˆ˜, ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๋˜๋Š” ์†์„ฑ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. -- ์•„๋ž˜์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ํ•จ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ docstring ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜ ์ด์ƒ์˜ ์†์„ฑ์„ ๊ฐ€์ง„ ๋ชจ๋“  ํ•จ์ˆ˜์—๋Š” docstring์ด ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค. - - ์™ธ๋ถ€์—์„œ ๋ณด์ด์ง€ ์•Š์Œ - - ๋งค์šฐ ์งง์Œ - - ์ž˜ ์•Œ๋ ค์ ธ ์žˆ์Œ + - ๊ณต๊ฐœ API์˜ ์ผ๋ถ€์ธ ๊ฒฝ์šฐ + - ๋น„๊ต์  ํฐ ๊ฒฝ์šฐ + - ์ง๊ด€์ ์ด์ง€ ์•Š์€ ๋กœ์ง์„ ๊ฐ€์ง„ ๊ฒฝ์šฐ -- docstring ์€ ์ง์ ‘ ํ•จ์ˆ˜์˜ ์ฝ”๋“œ๋ฅผ ์ฝ์–ด๋ณด์ง€ ์•Š๋”๋ผ๋„ ์ถฉ๋ถ„ํžˆ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ ํ•  ์ˆ˜ ์žˆ์„๋งŒํผ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- docstring์€ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ๋ฐฉ์‹์ด๋‚˜ ์‹œ๋ฉ˜ํ‹ฑ๋“ฑ์„ ๋ฐ˜๋“œ์‹œ ๊ธฐ์ˆ ํ•˜๋˜ ํ•จ์ˆ˜์˜ ์‚ฌ์šฉํ•จ์— ์žˆ์–ด ์˜ํ•ญ์„ ์ฃผ์ง€ ์•Š๋Š” ํ•œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์ƒ์„ธํ•œ ๊ตฌํ˜„๋ฐฉ๋ฒ•์€ ๊ธฐ์ˆ ํ•˜์ง€ ์•„๋‹ˆํ•ฉ๋‹ˆ๋‹ค -- ์˜ˆ๋ฅผ๋“ค์–ด ํ•œ ํ•จ์ˆ˜๊ฐ€ ๊ตฌ๋™๊ณผ์ •์—์„œ ์ธ์ž๋กœ ๋ฐ›์€ ๋ณ€์ˆ˜ ํ•˜๋‚˜๋ฅผ ๋ณ€ํ˜•์‹œํ‚จ๋‹ค๋ฉด ์ด๋Š” docstring์— ๊ธฐ์ˆ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์ด์™ธ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ๊ณผ ์ƒ๊ด€์ด ์—†๋Š” ์ž์ž˜ํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ ํ•ญ๋ชฉ๋“ค์€ ํ•จ์ˆ˜ ๋‚ด docstring ๋ณด๋‹จ ์ฃผ์„์œผ๋กœ ๊ธฐ๋กํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค -- docstring ์€ (`"""Fetches rows from a Bigtable."""`) ์ฒ˜๋Ÿผ _์„ค๋ช…์กฐ_ ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ์•ผ ํ•˜๋ฉฐ (`"""Fetch rows from a Bigtable."""`) ์ฒ˜๋Ÿผ _๋ช…๋ น์กฐ_ ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- docstring ์€ ํ•จ์ˆ˜์˜ ๊ตฌํ˜„๋ฐฉ์‹์ด ์•„๋‹Œ ํ˜ธ์ถœ ๋ฐฉ๋ฒ•๊ณผ ์˜๋ฏธ๋ฅผ ๊ธฐ์ˆ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋ณต์žกํ•œ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ docstring ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์ฝ”๋“œ ํ•œ ์ค„๋งˆ๋‹ค ์ฃผ์„์„ ์ฒจ๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ๋” ์•Œ๋งž์Šต๋‹ˆ๋‹ค. +- docstring์€ ํ•จ์ˆ˜์˜ ์ฝ”๋“œ๋ฅผ ์ฝ์ง€ ์•Š๊ณ ๋„ ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์„ ๋งŒํผ ์ถฉ๋ถ„ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- docstring์€ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ ๊ตฌ๋ฌธ๊ณผ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•ด์•ผ ํ•˜๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ ํฌํ•จํ•˜์ง€ ์•Š์•„์•ผ ํ•˜์ง€๋งŒ, ์ด๋Ÿฌํ•œ ์„ธ๋ถ€ ์‚ฌํ•ญ์ด ํ•จ์ˆ˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ์ค‘์š”ํ•˜๋‹ค๋ฉด ์˜ˆ์™ธ์ž…๋‹ˆ๋‹ค. +- ์˜ˆ๋ฅผ ๋“ค์–ด, ์ธ์ž๋ฅผ ์‚ฌ์ด๋“œ ์ž„ํŽ™ํŠธ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜๋Š” ๊ทธ ์ ์„ docstring์— ๋ช…์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋‹ค๋ฅธ ๊ธฐ๋ณธ ๊ฐ์ฒด์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋Š” `"""See base class."""` ์ฒ˜๋Ÿผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ docstring ์— ์˜ค๋ฒ„๋ผ์ด๋“œ๋œ ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ์Œ์„ ์•Œ๋ ค์ฃผ๋Š” docstring ์„ ์ „๋‹ฌ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -- ๊ทธ ์ด์œ ๋Š” ๊ฐ™์€ ๋ฌธ์„œ๋ฅผ ์—ฌ๋Ÿฌ๊ณณ์—์„œ ๋ฐ˜๋ณตํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. -- ํ•˜์ง€๋งŒ ์˜ค๋ฒ„๋ผ์ด๋”ฉ๋œ ๋ฉ”์†Œ๋“œ๊ฐ€ ๊ธฐ์กด์˜ ๋ฉ”์†Œ๋“œ์™€ ํ™•์—ฐํ•˜๊ฒŒ ๋‹ค๋ฅธ ๋™์ž‘๋ฐฉ์‹์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ฑฐ๋‚˜ ์„ธ๋ถ€์ ์ธ ๋‚ด์šฉ(e.g., ์ž ์žฌ์ ์ธ ๋ถ€์ž‘์šฉ ๋“ฑ)์ด ์กด์žฌํ•œ๋‹ค๋ฉด ์ ์–ด๋„ ๊ทธ๋Ÿฌํ•œ ์ฐจ์ด์ ๋“ค์€ docstring ์„ ํ†ตํ•ด ๊ธฐ๋ก๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, ํ˜ธ์ถœ์ž์—๊ฒŒ ์ค‘์š”ํ•˜์ง€ ์•Š์€ ํ•จ์ˆ˜ ๊ตฌํ˜„์˜ ๋ฏธ๋ฌ˜ํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ ํ•จ์ˆ˜์˜ docstring๋ณด๋‹ค๋Š” ์ฝ”๋“œ ์˜†์— ์ฃผ์„์œผ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. +- docstring์€ ์„œ์ˆ ํ˜•(`"""Fetches rows from a Bigtable."""`) ๋˜๋Š” ๋ช…๋ นํ˜•(`"""Fetch rows from a Bigtable."""`) ์Šคํƒ€์ผ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ํŒŒ์ผ ๋‚ด์—์„œ ์Šคํƒ€์ผ์€ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- `@property` ์†์„ฑ์˜ docstring์€ ์†์„ฑ์ด๋‚˜ [ํ•จ์ˆ˜ ์ธ์ž](#doc-function-args)์˜ docstring๊ณผ ๊ฐ™์€ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (`"""The Bigtable path."""` ๋Œ€์‹ ์— `"""Returns the Bigtable path."""`). -- ๋‹ค๋งŒ ํ•จ์ˆ˜์˜ ๋ช‡๊ฐ€์ง€ ํŠน์ • ๋ถ€๋ถ„๋“ค์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋ณ„๋„์˜ ํŠน๋ณ„์„น์…˜์œผ๋กœ ๊ธฐ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๊ฐ ์„น์…˜์€ ํ‘œ์ œ๋กœ ์‹œ์ž‘ํ•˜๋ฉฐ ์ฝœ๋ก ์œผ๋กœ ๋๋งบ์Šต๋‹ˆ๋‹ค. -- ๊ฐ ์„น์…˜์€ ํ‘œ์ œ๋ฅผ ์ œ์™ธํ•˜๊ณ  2์นธ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. +- ํ•จ์ˆ˜์˜ ํŠน์ • ์ธก๋ฉด์€ ์•„๋ž˜์— ๋‚˜์—ด๋œ ํŠน๋ณ„ํ•œ ์„น์…˜์—์„œ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๊ฐ ์„น์…˜์€ ์ฝœ๋ก ์œผ๋กœ ๋๋‚˜๋Š” ์ œ๋ชฉ ํ–‰์œผ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. +- ์ œ๋ชฉ์„ ์ œ์™ธํ•œ ๋ชจ๋“  ์„น์…˜์€ 2์นธ ๋˜๋Š” 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์œ ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (ํŒŒ์ผ ๋‚ด์—์„œ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€). +- ํ•จ์ˆ˜์˜ ์ด๋ฆ„๊ณผ ์‹œ๊ทธ๋‹ˆ์ฒ˜๊ฐ€ ์ถฉ๋ถ„ํžˆ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์—ฌ ํ•œ ์ค„์˜ docstring์œผ๋กœ ์ ์ ˆํžˆ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ, ์ด๋Ÿฌํ•œ ์„น์…˜์€ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -63,12 +97,13 @@ ##### [_Returns:_ (์ œ๋„ˆ๋ ˆ์ดํ„ฐ์—๋Š” _Yields:_)](#doc-function-returns) -- ๋ฐ˜ํ™˜๊ฐ’์˜ ์ž๋ฃŒํ˜•๊ณผ ์˜๋ฏธ๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ•จ์ˆ˜๊ฐ€ None๋งŒ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋ฉด ์ด ์„น์…˜์€ ํ•„์š”์—†์Šต๋‹ˆ๋‹ค. -- ๋˜ํ•œ ๋งŒ์•ฝ docstring์ด Returns ๋‚˜ Yields๋กœ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜(e.g. `"""Returns row from Bigtable as a tuple of strings."""`) ์ถฉ๋ถ„ํ•œ ์„ค๋ช…์ด ์ œ๊ณต๋œ๋‹ค๋ฉด ์ƒ๋žต ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -- Tuple ๋ฐ˜ํ™˜ ๊ฐ’์„ ๊ฐœ๋ณ„ ์ด๋ฆ„์ด ์žˆ๋Š” ์—ฌ๋Ÿฌ ๋ฐ˜ํ™˜ ๊ฐ’์ธ ๊ฒƒ์ฒ˜๋Ÿผ ์ž์ฃผ ๋ฌธ์„œํ™”ํ•˜๋Š” 'NumPy style' ([example](http://numpy.org/doc/stable/reference/generated/numpy.linalg.qr.html))์„ ๋ชจ๋ฐฉํ•˜์ง€ ๋งˆ์„ธ์š”. (Tuple๋ฅผ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.) -- ๋Œ€์‹ , ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ๊ธฐ์ˆ ํ•˜์„ธ์š”. - - "Returns a tuple (mat_a, mat_b), where mat_a is ..., and ...". -- Docstring์˜ ๋ณด์กฐ ์ด๋ฆ„์€ ํ•จ์ˆ˜ ๋ณธ๋ฌธ์— ์‚ฌ์šฉ๋œ ๋‚ด๋ถ€ ์ด๋ฆ„๊ณผ ๋ฐ˜๋“œ์‹œ ์ผ์น˜ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. (ํ•ด๋‹น ์ด๋ฆ„์€ API์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.) +- ๋ฐ˜ํ™˜ ๊ฐ’์˜ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•˜๊ณ , ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์—์„œ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ํƒ€์ž… ์ •๋ณด๋„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ํ•จ์ˆ˜๊ฐ€ None๋งŒ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ, ์ด ์„น์…˜์€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- docstring์ด "Return", "Returns", "Yield", "Yields"๋กœ ์‹œ์ž‘ํ•˜๊ณ (e.g. `"""Returns row from Bigtable as a tuple of strings."""`), ์ฒซ ๋ฒˆ์งธ ๋ฌธ์žฅ์ด ๋ฐ˜ํ™˜ ๊ฐ’์„ ์„ค๋ช…ํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•  ๊ฒฝ์šฐ, ์ด ์„น์…˜์€ ์ƒ๋žต๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- ์ด์ „์˜ 'NumPy ์Šคํƒ€์ผ'์„ ๋ชจ๋ฐฉํ•˜์ง€ ๋งˆ์„ธ์š”. ([example](https://numpy.org/doc/1.24/reference/generated/numpy.linalg.qr.html)) ์ด ์Šคํƒ€์ผ์€ ์ข…์ข… ํŠœํ”Œ ๋ฐ˜ํ™˜ ๊ฐ’์„ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐœ๋ณ„ ๋ฐ˜ํ™˜ ๊ฐ’์ฒ˜๋Ÿผ ๊ฐ๊ฐ์˜ ์ด๋ฆ„์œผ๋กœ ๋ฌธ์„œํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค. (ํŠœํ”Œ์ด๋ผ๋Š” ์ ์„ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š๊ณ ) +- ๋Œ€์‹ , ๋ฐ˜ํ™˜ ๊ฐ’์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๋ช…ํ•˜์„ธ์š”: "Returns: A tuple (mat_a, mat_b), where mat_a is ..., and ...". +- docstring์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์„ค๋ช…์šฉ ์ด๋ฆ„์€ ํ•จ์ˆ˜ ๋ณธ๋ฌธ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋‚ด๋ถ€ ์ด๋ฆ„๊ณผ ๋ฐ˜๋“œ์‹œ ์ผ์น˜ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค (๋‚ด๋ถ€ ์ด๋ฆ„์€ API์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค) +- ํ•จ์ˆ˜๊ฐ€ `yield`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ(์ฆ‰, ์ œ๋„ˆ๋ ˆ์ดํ„ฐ์ธ ๊ฒฝ์šฐ), `Yields:` ์„น์…˜์—์„œ๋Š” ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋กœ ๋ฐ˜ํ™˜๋˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ, `next()`์— ์˜ํ•ด ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -79,10 +114,11 @@ - ๋ช…์‹œ๋œ API๊ฐ€ docstring์„ ์œ„๋ฐ˜ํ–ˆ์„ ๋  ๊ฒฝ์šฐ, ์˜ˆ์™ธ๋ฅผ ๋ฌธ์„œํ™”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. (์™œ๋ƒํ•˜๋ฉด ์ด๊ฒƒ์€ ์—ญ์„ค์ ์œผ๋กœ API์˜ API๋ฅผ ์œ„๋ฐ˜ํ•˜๋Š” ํ–‰๋™์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.) ```python - def fetch_smalltable_rows(table_handle: smalltable.Table, - keys: Sequence[Union[bytes, str]], - require_all_keys: bool = False, - ) -> Mapping[bytes, Tuple[str, ...]]: + def fetch_smalltable_rows( + table_handle: smalltable.Table, + keys: Sequence[bytes | str], + require_all_keys: bool = False, + ) -> Mapping[bytes, tuple[str, ...]]: """Fetches rows from a Smalltable. Retrieves rows pertaining to the given keys from the Table instance @@ -116,10 +152,11 @@ - ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ์ค„ ๋ฐ”๊ฟˆ์ด ์žˆ๋Š” `Args:`๋„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ```python - def fetch_smalltable_rows(table_handle: smalltable.Table, - keys: Sequence[Union[bytes, str]], - require_all_keys: bool = False, - ) -> Mapping[bytes, Tuple[str, ...]]: + def fetch_smalltable_rows( + table_handle: smalltable.Table, + keys: Sequence[bytes | str], + require_all_keys: bool = False, + ) -> Mapping[bytes, tuple[str, ...]]: """Fetches rows from a Smalltable. Retrieves rows pertaining to the given keys from the Table instance @@ -152,19 +189,51 @@ """ ``` + + + +##### 3.8.3.1 Overridden Methods + +- ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” [`@override`](https://typing-extensions.readthedocs.io/en/latest/#override) ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ(`typing_extensions` ๋˜๋Š” `typing` ๋ชจ๋“ˆ์—์„œ ์ œ๊ณต)๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ docstring์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- ๋‹จ, ์˜ค๋ฒ„๋ผ์ด๋”ฉ๋œ ๋ฉ”์„œ๋“œ์˜ ๋™์ž‘์ด ๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ์˜ ๊ณ„์•ฝ์„ ์‹ค์งˆ์ ์œผ๋กœ ๊ฐœ์„ ํ•˜๊ฑฐ๋‚˜, ์ถ”๊ฐ€์ ์ธ ์‚ฌ์ด๋“œ ์ž„ํŽ™ํŠธ ๋“ฑ์„ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š”, ๊ทธ๋Ÿฌํ•œ ์ฐจ์ด์ ์ด ์ตœ์†Œํ•œ ํฌํ•จ๋œ docstring์ด ์˜ค๋ฒ„๋ผ์ด๋”ฉ ๋ฉ”์„œ๋“œ์— ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + + ```python + from typing_extensions import override + class Parent: + def do_something(self): + """Parent method, includes docstring.""" + # ์ž์‹ ํด๋ž˜์Šค, ์˜ค๋ฒ„๋ผ์ด๋“œ๋กœ ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ๋ฉ”์„œ๋“œ. + class Child(Parent): + @override + def do_something(self): + pass + ``` + + ```python + # ์ž์‹ ํด๋ž˜์Šค์—์„œ @override ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ, docstring์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + class Child(Parent): + def do_something(self): + pass + # docstring์ด ๋‹จ์ˆœํ•œ ๊ฒฝ์šฐ, @override๋งŒ์œผ๋กœ๋„ ๋ฌธ์„œ๊ฐ€ ๊ธฐ๋ณธ ํด๋ž˜์Šค์— ์žˆ์Œ์„ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + class Child(Parent): + @override + def do_something(self): + """See base class.""" + ``` + #### 3.8.4 Classes - ํด๋ž˜์Šค๋Š” ์„ ์–ธ ๋ฐ”๋กœ ์•„๋ž˜์— ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์„ค๋ช…ํ•˜๋Š” docstring ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋งŒ์•ฝ ํด๋ž˜์Šค๊ฐ€ public attributes ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด [function's `Args`](#doc-function-args) ์„น์…˜๊ณผ ๊ฐ™์€ ํ˜•์‹์„ ์‚ฌ์šฉํ•ด `Attributes` ์„น์…˜์„ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- [properties](#properties)์„ ์ œ์™ธํ•œ ๊ณต๊ฐœ ์†์„ฑ์€ `Attributes` ์„น์…˜์—์„œ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•˜๋ฉฐ, [ํ•จ์ˆ˜์˜ `Args`](#doc-function-args) ์„น์…˜๊ณผ ๋™์ผํ•œ ํ˜•์‹์„ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ```python class SampleClass: """Summary of class here. - Longer class information.... - Longer class information.... + Longer class information... + Longer class information... Attributes: likes_spam: A boolean indicating if we like SPAM or not. @@ -172,14 +241,42 @@ class SampleClass: """ def __init__(self, likes_spam: bool = False): - """Inits SampleClass with blah.""" + """Initializes the instance based on spam preference. + Args: + likes_spam: Defines if instance exhibits this preference. + """ self.likes_spam = likes_spam self.eggs = 0 - def public_method(self): - """Performs operation blah.""" + @property + def butter_sticks(self) -> int: + """The number of butter sticks we have.""" ``` +- ๋ชจ๋“  ํด๋ž˜์Šค์˜ docstring์€ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฌด์—‡์„ ๋‚˜ํƒ€๋‚ด๋Š”์ง€๋ฅผ ์„ค๋ช…ํ•˜๋Š” ํ•œ ์ค„ ์š”์•ฝ์œผ๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” `Exception`์˜ ์„œ๋ธŒํด๋ž˜์Šค๋„ ์˜ˆ์™ธ๊ฐ€ ๋ฌด์—‡์„ ๋‚˜ํƒ€๋‚ด๋Š”์ง€๋ฅผ ์„ค๋ช…ํ•ด์•ผ ํ•˜๋ฉฐ, ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•ด์„œ๋Š” ์„ค๋ช…ํ•˜์ง€ ์•Š์•„์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ํด๋ž˜์Šค์˜ docstring์€ ํด๋ž˜์Šค๊ฐ€ ํด๋ž˜์Šค๋ผ๋Š” ๋“ฑ์˜ ๋ถˆํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. + +- ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ + + ```python + class CheeseShopAddress: + """The address of a cheese shop. + ... + """ + class OutOfCheeseError(Exception): + """No more cheese is available.""" + ``` + +- ๋ถ€์ ์ ˆํ•œ ์˜ˆ + + ```python + class CheeseShopAddress: + """Class that describes the address of a cheese shop. + ... + """ + class OutOfCheeseError(Exception): + """Raised when no more cheese is available.""" + ``` + diff --git "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/ReadMe.md" "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/ReadMe.md" index 41c38b2..2a79363 100644 --- "a/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/ReadMe.md" +++ "b/Google Python Style Guide/3. Python \354\212\244\355\203\200\354\235\274 \352\267\234\354\271\231/ReadMe.md" @@ -17,10 +17,10 @@ - ๊ฒฝ๋กœ์ด๋ฆ„์ด๋‚˜ URLs์™€ ๊ฐ™์€ ๊ณต๋ฐฑ์„ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ๊ธด ๋ชจ๋“ˆ์ˆ˜์ค€ ๋ฌธ์ž์ƒ์ˆ˜๋Š” ์—ฌ๋Ÿฌ ์ค„์— ๋‚˜๋ˆ„์–ด ๊ธฐ๋กํ•˜๊ธฐ ๋ถˆํŽธํ•  ๊ฒฝ์šฐ - Pylint ๋น„ํ™œ์„ฑํ™” ์ฃผ์„๋ฌธ (e.g.: `# pylint: disable=invalid-name`) -- 3๊ฐœ ์ด์ƒ์˜ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €๋ฅผ ์š”๊ตฌํ•˜๋Š” `with` ๊ตฌ๋ฌธ์„ ์ œ์™ธํ•˜๊ณ  ๋ฐฑ์Šฌ๋ž˜์‰ฌ(`\`) ๋ฅผ ์ด์šฉํ•œ ๋ฌธ์žฅ์—ฐ์žฅ์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. - -- Python์˜ [์†Œ/์ค‘/๋Œ€ ๊ด„ํ˜ธ ๋‚ด๋ถ€์˜ ๋ฌต์‹œ์  ๋ผ์ธ๊ฒฐํ•ฉ](http://docs.python.org/reference/lexical_analysis.html#implicit-line-joining)์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- [๋ช…์‹œ์ ์ธ ์ค„ ์—ฐ์†](https://docs.python.org/3/reference/lexical_analysis.html#explicit-line-joining)์„ ์œ„ํ•ด ๋ฐฑ์Šฌ๋ž˜์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. +- ๋Œ€์‹ ์— Python์˜ [์†Œ/์ค‘/๋Œ€ ๊ด„ํ˜ธ ๋‚ด๋ถ€์˜ ๋ฌต์‹œ์  ๋ผ์ธ๊ฒฐํ•ฉ](http://docs.python.org/reference/lexical_analysis.html#implicit-line-joining)์„ ์‚ฌ์šฉํ•˜์„ธ์š”. - ํ•„์š”ํ•˜๋‹ค๋ฉด, ๊ตฌ๋ฌธ ์–‘์ชฝ์— ์ถ”๊ฐ€๋กœ ๊ด„ํ˜ธ๋ฅผ ๋”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- ์ด ๊ทœ์น™์€ ๋ฌธ์ž์—ด ๋‚ด์—์„œ ๋ฐฑ์Šฌ๋ž˜์‹œ๋กœ ์ด์Šค์ผ€์ดํ”„๋œ ๊ฐœํ–‰์„ ๊ธˆ์ง€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์•„๋ž˜ [์ฐธ์กฐ](#strings)). - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -28,8 +28,29 @@ foo_bar(self, width, height, color='black', design=None, x='foo', emphasis=None, highlight=0) - if (width == 0 and height == 0 and - color == 'red' and emphasis == 'strong'): + if (width == 0 and height == 0 and + color == 'red' and emphasis == 'strong'): + (bridge_questions.clarification_on + .average_airspeed_of.unladen_swallow) = 'African or European?' + with ( + very_long_first_expression_function() as spam, + very_long_second_expression_function() as beans, + third_thing() as eggs, + ): + place_order(eggs, beans, spam, beans) + ``` + + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ + + ```python + if width == 0 and height == 0 and \ + color == 'red' and emphasis == 'strong': + bridge_questions.clarification_on \ + .average_airspeed_of.unladen_swallow = 'African or European?' + with very_long_first_expression_function() as spam, \ + very_long_second_expression_function() as beans, \ + third_thing() as eggs: + place_order(eggs, beans, spam, beans) ``` - ๋งŒ์•ฝ ๋ฆฌํ„ฐ๋Ÿด ๋ฌธ์ž์—ด์„ ํ•œ ์ค„์— ํ‘œํ˜„ํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ด„ํ˜ธ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฌต์‹œ์  ๋ผ์ธ๊ฒฐํ•ฉ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -39,56 +60,55 @@ 'long long long long long long string') ``` -- ์ฃผ์„์˜ ๊ฒฝ์šฐ ๊ธด URLs ๋“ค์€ ํ•œ์ค„์— ํ‘œํ˜„ํ•˜์„ธ์š”. +- ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ๋†’์€ ๊ตฌ๋ฌธ ์ˆ˜์ค€์—์„œ ์ค„์„ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜์„ธ์š”. ์ค„์„ ๋‘ ๋ฒˆ ๋‚˜๋ˆ ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ, ๋‘ ๋ฒˆ ๋ชจ๋‘ ๋™์ผํ•œ ๊ตฌ๋ฌธ ์ˆ˜์ค€์—์„œ ๋‚˜๋ˆ„์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - # See details at - # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html + bridgekeeper.answer( + name="Arthur", quest=questlib.find(owner="Arthur", perilous=True)) + answer = (a_long_line().of_chained_methods() + .that_eventually_provides().an_answer()) + if ( + config is None + or 'editor.language' not in config + or config['editor.language'].use_spaces is False + ): + use_tabs() ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - # See details at - # http://www.example.com/us/developer/documentation/api/content/\ - # v2.0/csv_file_name_extension_full_specification.html + bridgekeeper.answer(name="Arthur", quest=questlib.find( + owner="Arthur", perilous=True)) + answer = a_long_line().of_chained_methods().that_eventually_provides( + ).an_answer() + if (config is None or 'editor.language' not in config or config[ + 'editor.language'].use_spaces is False): + use_tabs() ``` -- 3์ค„ ์ด์ƒ์ด ํ•„์š”ํ•œ `with` ๊ตฌ๋ฌธ์„ ์ •์˜ํ•  ๋•Œ๋Š” ๋ฐฑ์Šฌ๋ž˜์‰ฌ(`\`) ๋ฅผ ์ด์šฉํ•œ ๋ฌธ์žฅ์—ฐ์žฅ์ด ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. 2์ค„์ธ ๊ฒฝ์šฐ ๋„ค์Šคํ‹ฐ๋“œ `with`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š” +- ์ฃผ์„์˜ ๊ฒฝ์šฐ ๊ธด URLs ๋“ค์€ ํ•œ์ค„์— ํ‘œํ˜„ํ•˜์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - with very_long_first_expression_function() as spam, \ - very_long_second_expression_function() as beans, \ - third_thing() as eggs: - place_order(eggs, beans, spam, beans) + # See details at + # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - with VeryLongFirstExpressionFunction() as spam, \ - VeryLongSecondExpressionFunction() as beans: - PlaceOrder(beans, spam) - ``` - - - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ - - ```python - with very_long_first_expression_function() as spam: - with very_long_second_expression_function() as beans: - place_order(beans, spam) + # See details at + # http://www.example.com/us/developer/documentation/api/content/\ + # v2.0/csv_file_name_extension_full_specification.html ``` - ์œ„์˜ ์˜ˆ์‹œ์—์„œ ๊ฐ ์š”์†Œ์— ์‚ฌ์šฉ๋œ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์ž˜ ๊ธฐ์–ตํ•˜์„ธ์š”. ๋” ์ž์„ธํ•œ ์ •๋ณด๋Š” [๋“ค์—ฌ์“ฐ๊ธฐ](#s3.4-indentation) ์ฑ•ํ„ฐ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. +- ์œ„์—์„œ ์–ธ๊ธ‰๋˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ ํ•œ ์ค„์˜ ๊ธธ์ด๊ฐ€ 80์ž๋ฅผ ์ดˆ๊ณผํ•จ์—๋„ [Black](https://github.com/psf/black) ํ˜น์€ [Pyink](https://github.com/google/pyink) ์˜คํ† ํฌ๋ฉ”ํ„ฐ๊ฐ€ ๋ณ„๋‹ค๋ฅธ ๋„์›€์„ ์ฃผ์ง€ ๋ชปํ•œ๋‹ค๋ฉด 80์ž ์ด์ƒ ์ดˆ๊ณผ๊ฐ€ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ž‘์„ฑ์ž๋Š” ์ƒ์‹์ ์ธ ์ˆ˜์ค€๋‚ด์—์„œ ์œ„ ๋ฌธ์„œ์˜ ์‚ฌํ•ญ์„ ์ฐธ๊ณ ํ•˜์—ฌ ์ค„์„ ๋ถ„๋ฆฌํ•˜๋Š”๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•ฉ๋‹ˆ๋‹ค. -์œ„์—์„œ ์–ธ๊ธ‰๋˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ ํ•œ ์ค„์˜ ๊ธธ์ด๊ฐ€ 80์ž๋ฅผ ์ดˆ๊ณผํ•จ์—๋„ -[yapf](https://github.com/google/yapf/) -์˜คํ† ํฌ๋ฉ”ํ„ฐ๊ฐ€ ๋ณ„๋‹ค๋ฅธ ๋„์›€์„ ์ฃผ์ง€ ๋ชปํ•œ๋‹ค๋ฉด 80์ž ์ด์ƒ ์ดˆ๊ณผ๊ฐ€ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. -์ž‘์„ฑ์ž๋Š” ์ƒ์‹์ ์ธ ์ˆ˜์ค€๋‚ด์—์„œ ์œ„ ๋ฌธ์„œ์˜ ์‚ฌํ•ญ์„ ์ฐธ๊ณ ํ•˜์—ฌ ์ค„์„ ๋ถ„๋ฆฌํ•˜๋Š”๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•ฉ๋‹ˆ๋‹ค. --- @@ -135,26 +155,26 @@ - ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ _4 ์นธ_ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ํ•˜์„ธ์š”. -- ํƒญ์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํƒญ๊ณผ ์ŠคํŽ˜์ด์Šค๋ฅผ ์„ž์–ด์„œ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. -- ๋ฌต์‹œ์  ๋ฌธ์žฅ์—ฐ์žฅ์˜ ๊ฒฝ์šฐ [line length](#s3.2-line-length) ์„น์…˜์˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ๋™์ผํ•œ ๋ฌธ์žฅ์— ํฌํ•จ๋œ ์š”์†Œ๋“ค์„ ์ˆ˜์ง์ •๋ ฌํ•˜๊ฑฐ๋‚˜ ์ฒซ ์—ด๋ฆฐ๊ด„ํ˜ธ ์ดํ›„๋กœ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†๋Š” 4 ์นธ hanging indent ๋ฅผ ์ ์šฉํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ํƒญ์„ ์ ˆ๋Œ€ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. ์•”์‹œ๋œ ์ค„ ์—ฐ์†์€ ๋ž˜ํ•‘๋œ ์š”์†Œ๋ฅผ ์ˆ˜์ง์œผ๋กœ ์ •๋ ฌํ•ด์•ผ ํ•˜๋ฉฐ([์ค„ ๊ธธ์ด ์˜ˆ์ œ](#s3.2-line-length) ์ฐธ์กฐ), ๋˜๋Š” 4๊ฐœ์˜ ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ–‰์„ ๋“ค์—ฌ์“ฐ๊ธฐ ํ•˜์„ธ์š”. +- ๋‹ซ๋Š” ๊ด„ํ˜ธ(์›, ๋Œ€๊ฐ์„  ๋˜๋Š” ์ค‘๊ด„ํ˜ธ)๋Š” ํ‘œํ˜„์‹์˜ ๋์— ๋ฐฐ์น˜ํ•˜๊ฑฐ๋‚˜ ๋ณ„๋„์˜ ์ค„์— ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด ๊ฒฝ์šฐ ํ•ด๋‹น ์—ฌ๋Š” ๊ด„ํ˜ธ์™€ ๊ฐ™์€ ์ค„์— ๋“ค์—ฌ์“ฐ๊ธฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - # Aligned with opening delimiter + # ์—ฌ๋Š” ๊ตฌ๋ถ„ ๊ธฐํ˜ธ์™€ ์ •๋ ฌ๋จ foo = long_function_name(var_one, var_two, var_three, var_four) meal = (spam, beans) - # Aligned with opening delimiter in a dictionary + # ๋”•์…”๋„ˆ๋ฆฌ์˜ ์—ฌ๋Š” ๊ตฌ๋ถ„ ๊ธฐํ˜ธ์™€ ์ •๋ ฌ๋จ foo = { 'long_dictionary_key': value1 + value2, ... } - # 4-space hanging indent; nothing on first line + # 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ, ์ฒซ ๋ฒˆ์งธ ์ค„์—๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†์Œ foo = long_function_name( var_one, var_two, var_three, var_four) @@ -162,7 +182,16 @@ spam, beans) - # 4-space hanging indent in a dictionary + # 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ; ์ฒซ ๋ฒˆ์งธ ์ค„์—๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†์Œ, ๋‹ซ๋Š” ๊ด„ํ˜ธ๋Š” ์ƒˆ ์ค„์— ๋ฐฐ์น˜ + foo = long_function_name( + var_one, var_two, var_three, + var_four + ) + meal = ( + spam, + beans, + ) + # ๋”•์…”๋„ˆ๋ฆฌ์—์„œ 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ foo = { 'long_dictionary_key': long_dictionary_value, @@ -173,18 +202,18 @@ - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - # Stuff on first line forbidden + # ์ฒซ ๋ฒˆ์งธ ์ค„์— ๋‚ด์šฉ์ด ์žˆ์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. foo = long_function_name(var_one, var_two, var_three, var_four) meal = (spam, beans) - # 2-space hanging indent forbidden + # 2์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ๋Š” ๊ธˆ์ง€๋ฉ๋‹ˆ๋‹ค. foo = long_function_name( var_one, var_two, var_three, var_four) - # No hanging indent in a dictionary + # ๋”•์…”๋„ˆ๋ฆฌ์—์„œ๋Š” ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. foo = { 'long_dictionary_key': long_dictionary_value, @@ -196,8 +225,8 @@ #### 3.4.1 ์›์†Œ ๋‚˜์—ด ์‹œ ํ›„ํ–‰ ์‰ผํ‘œ -- ์—ฌ๋Ÿฌ ์›์†Œ๋ฅผ ๋‚˜์—ดํ•  ๋•Œ ํ›„ํ–‰ ์‰ผํ‘œ๋Š” `]`, `)`, `}` ์™€ ๊ฐ™์ด ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋‹ซ๋Š” ํ† ํฐ์ด ๋งˆ์ง€๋ง‰ ์›์†Œ์™€ ๊ฐ™์€ ์ค„์— ์žˆ์ง€ ์•Š์„ ๋•Œ๋งŒ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. -- ๋˜ํ•œ ํ›„ํ–‰ ์‰ผํ‘œ์˜ ์กด์žฌ ์—ฌ๋ถ€๋Š” ํŒŒ์ด์ฌ ์ฝ”๋“œ ์˜คํ† -ํฌ๋ฉ”ํ„ฐ [YAPF](https://pypi.org/project/yapf/) ๊ฐ€ ์ปจํ…Œ์ด๋„ˆ์˜ ์›์†Œ๋ฅผ ํ•œ ์ค„์— ํ•˜๋‚˜์”ฉ `,` ๊ธฐํ˜ธ๋ฅผ ๋ถ™์—ฌ ์ž๋™ ์ •๋ ฌํ•˜๋„๋ก ์ง€์‹œํ•˜๋Š” ํžŒํŠธ๋กœ๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. +- ํ›„ํ–‰ ์‰ผํ‘œ๋Š” ์‹œํ€€์Šค์˜ ์š”์†Œ์—์„œ ๋‹ซ๋Š” ๊ตฌ๋ฌธ ๊ธฐํ˜ธ `]`, `)`, ๋˜๋Š” `}`๊ฐ€ ๋งˆ์ง€๋ง‰ ์š”์†Œ์™€ ๊ฐ™์€ ์ค„์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์™€ ๋‹จ์ผ ์š”์†Œ๋ฅผ ๊ฐ€์ง„ ํŠœํ”Œ์— ๋Œ€ํ•ด์„œ๋งŒ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. +- ํ›„ํ–‰ ์‰ผํ‘œ์˜ ์กด์žฌ๋Š” Python ์ฝ”๋“œ ์ž๋™ ํฌ๋งทํ„ฐ์ธ [Black](https://github.com/psf/black)์ด๋‚˜ [Pyink](https://github.com/google/pyink)์—๊ฒŒ ๋งˆ์ง€๋ง‰ ์š”์†Œ ๋’ค์— `,`๊ฐ€ ์žˆ์„ ๋•Œ ํ•ญ๋ชฉ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ•œ ์ค„์— ํ•˜๋‚˜์˜ ํ•ญ๋ชฉ์”ฉ ์ž๋™์œผ๋กœ ํฌ๋งทํ•˜๋„๋ก ์ง€์‹œํ•˜๋Š” ํžŒํŠธ๋กœ๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -218,8 +247,7 @@ 0, 1, 4, - 6 - ] + 6,] ``` --- @@ -228,7 +256,7 @@ ### 3.5 Blank Lines - ํ•จ์ˆ˜ ์„ ์–ธ์ด๋“  ๊ฐ์ฒด ์„ ์–ธ์ด๋“  ์ตœ์ƒ์œ„ ์„ ์–ธ๋ฌธ๊ณผ๋Š” 2๊ฐœ์˜ ๋นˆ ์ค„์„ ์‚ฌ์ด์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๊ฐ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ๋˜๋Š” `class` ์ค„๊ณผ ์ “ ๋ฒˆ์งธ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ์‹œ ๊ทธ ์‚ฌ์ด์—๋Š” ํ•œ ๊ฐœ์˜ ๋นˆ ์ค„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๊ฐ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ๋˜๋Š” `class`์˜ docstring ์ค„๊ณผ ์ “ ๋ฒˆ์งธ ๋ฉ”์†Œ๋“œ ์„ ์–ธ ์‹œ ๊ทธ ์‚ฌ์ด์—๋Š” ํ•œ ๊ฐœ์˜ ๋นˆ ์ค„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - `def` ์ค„ ์ดํ›„์—๋Š” ๋นˆ ์ค„์ด ์—†์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ํ•จ์ˆ˜์™€ ๋ฉ”์†Œ๋“œ ์‚ฌ์ด์— ๊ฐœ๋ฐœ์ž์˜ ํŒ๋‹จํ•˜์— ์ ์ ˆํ•˜๊ฒŒ ํ•œ ๊ฐœ์˜ ๋นˆ ์ค„์„ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -366,7 +394,7 @@ ### 3.7 Shebang Line - ๋Œ€๋ถ€๋ถ„์˜ `.py` ํŒŒ์ผ์€ `#!` ๋กœ ์‹œ์ž‘ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. -- [PEP-394](https://www.python.org/dev/peps/pep-0394/)์— ๋”ฐ๋ผ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ฉ”์ธ ํŒŒ์ผ ์ฒซ ์ค„์— `#!/usr/bin/env python3` (virtualenvs ์ง€์›) ๋˜๋Š” `#!/usr/bin/python3`์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. +- [PEP-394](https://peps.python.org/pep-0394/)์— ๋”ฐ๋ผ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ฉ”์ธ ํŒŒ์ผ ์ฒซ ์ค„์— `#!/usr/bin/env python3` (virtualenvs ์ง€์›) ๋˜๋Š” `#!/usr/bin/python3`์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. - ์ด ์ค„์€ ํŒŒ์ด์ฌ ํŒŒ์ผ์„ import ํ• ๋•Œ๋Š” ๋ฌด์‹œ๋˜์ง€๋งŒ ์‹คํ–‰ ๋ ๋•Œ๋Š” ์ปค๋„์ด ์–ด๋–ค ํŒŒ์ด์ฌ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. - ๋”ฐ๋ผ์„œ ์ง์ ‘ ์‹คํ–‰๋  ํŒŒ์ผ์— ๊ธฐ๋กํ•˜๋Š”๊ฒƒ์ด ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. @@ -385,7 +413,7 @@ - ํŒŒ์ด์ฌ์€ ์ฝ”๋“œ๋ฅผ ๋ฌธ์„œํ™” ํ•  ๋•Œ _docstring_ ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. - docstring ์€ ํŒจํ‚ค์ง€, ๋ชจ๋“ˆ, ํด๋ž˜์Šค๋‚˜ ํ•จ์ˆ˜์˜ ์ฒซ๋ฒˆ์งธ ์„ ์–ธ๋˜๋Š” ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. - ์ด ๋ฌธ์ž์—ด์€ `pydoc` ์ด ์‚ฌ์šฉํ•˜๋Š” `__doc__` ๋ฉค๋ฒ„ ์˜ค๋ธŒ์ ํŠธ์—์„œ ์ž๋™์œผ๋กœ ์ถ”์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์—ฌ๋Ÿฌ๋ถ„์˜ ๋ชจ๋“ˆ์—์„œ `pydoc` ๋ฅผ ์‹คํ–‰ ํ›„ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ณด์„ธ์š”) -- [PEP257](https://www.google.com/url?sa=D&q=http://www.python.org/dev/peps/pep-0257/) ์— ๋”ฐ๋ผ docstring ์„ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋๋‚ผ ๋•Œ๋Š” `"""` ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. +- [PEP257](https://peps.python.org/pep-0257/) ์— ๋”ฐ๋ผ docstring ์„ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ๋๋‚ผ ๋•Œ๋Š” `"""` ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. - docstring์€ ๋งˆ์นจํ‘œ, ๋ฌผ์Œํ‘œ, ๋Š๋‚Œํ‘œ๋กœ ๋๋‚˜๋Š” ์š”์•ฝ์ค„(ํ•œ ์ค„)๋กœ ์‹œ์ž‘ํ•˜์—ฌ์•ผ ํ•˜๋ฉฐ ํ•œ ์ค„์˜ ๊ณต๋ฐฑ์„ ๋‘๊ณ  ๋‚ด์šฉ์„ ๋‹ด๊ณ ์žˆ๋Š” ๋‚˜๋จธ์ง€ docstring ์ด ์ด์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ๋˜ํ•œ ๋‚ด์šฉ์„ ๋‹ด๊ณ ์žˆ๋Š” docstring ์€ `"""` ์™€ ๊ฐ™์€ ์ปค์„œ์œ„์น˜์—์„œ ์‹œ์ž‘ํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -393,36 +421,70 @@ #### 3.8.2 Modules -- ๋ชจ๋“  ํŒŒ์ผ์€ ๋ผ์ด์„ผ์Šค ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ํ”„๋กœ์ ํŠธ์— ์•Œ๋งž๋Š” ๋ผ์ด์„ผ์Šค ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ์„ ํƒํ•˜์„ธ์š”. (์˜ˆ๋ฅผ ๋“ค๋ฉด, Apache 2.0, BSD, LGPL, GPL) +- ๋ชจ๋“  ํŒŒ์ผ์€ ๋ผ์ด์„ผ์Šค ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + + ```python + """๋ชจ๋“ˆ์ด๋‚˜ ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•œ ํ•œ ์ค„ ์š”์•ฝ์œผ๋กœ, ๋งˆ์นจํ‘œ๋กœ ๋๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. + + ํ•œ ์ค„์„ ๋น„์›Œ๋‘์„ธ์š”. ์ด docstring์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์—๋Š” ๋ชจ๋“ˆ์ด๋‚˜ ํ”„๋กœ๊ทธ๋žจ์— + ๋Œ€ํ•œ ์ „๋ฐ˜์ ์ธ ์„ค๋ช…์ด ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์„ ํƒ์ ์œผ๋กœ, ๋‚ด๋ณด๋‚ธ ํด๋ž˜์Šค์™€ + ํ•จ์ˆ˜์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ์„ค๋ช… ๋ฐ/๋˜๋Š” ์‚ฌ์šฉ ์˜ˆ์‹œ๋„ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + ์ „ํ˜•์ ์ธ ์‚ฌ์šฉ ์˜ˆ์‹œ: + + foo = ClassFoo() + bar = foo.FunctionBar() + """ + ``` + + + + +##### 3.8.2.1 Test modules + +- ํ…Œ์ŠคํŠธ ํŒŒ์ผ์˜ ๋ชจ๋“ˆ ์ˆ˜์ค€ docstring์€ ํ•„์ˆ˜๋Š” ์•„๋‹™๋‹ˆ๋‹ค. +- ์ถ”๊ฐ€์ ์ธ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•  ํ•„์š”๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์˜ˆ๋ฅผ ๋“ค๋ฉด, ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ๋‚ด์šฉ, ํŠน์ดํ•œ ์„ค์ • ํŒจํ„ด์— ๋Œ€ํ•œ ์„ค๋ช…, ์™ธ๋ถ€ ํ™˜๊ฒฝ์— ๋Œ€ํ•œ ์˜์กด์„ฑ ๋“ฑ์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +"""์ด Blaze ํ…Œ์ŠคํŠธ๋Š” golden ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +`google3` ๋””๋ ‰ํ† ๋ฆฌ์—์„œ +`blaze run //foo/bar:foo_test -- --update_golden_files` ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜์—ฌ +์ด๋Ÿฌํ•œ ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +""" +``` + +- ์ƒˆ๋กœ์šด ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” docstring์€ ์‚ฌ์šฉํ•˜์ง€ ๋ง์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +```python +"""Tests for foo.bar.""" +``` #### 3.8.3 Functions and Methods -- ์ด ์„น์…˜์—์„œ "ํ•จ์ˆ˜"๋Š” ๋ฉ”์†Œ๋“œ, ํ•จ์ˆ˜ ๋˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. +- ์ด ์„น์…˜์—์„œ โ€˜functionโ€™์€ ๋ฉ”์†Œ๋“œ, ํ•จ์ˆ˜, ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๋˜๋Š” ์†์„ฑ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. -- ์•„๋ž˜์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ํ•จ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ docstring ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜ ์ด์ƒ์˜ ์†์„ฑ์„ ๊ฐ€์ง„ ๋ชจ๋“  ํ•จ์ˆ˜์—๋Š” docstring์ด ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค. - - ์™ธ๋ถ€์—์„œ ๋ณด์ด์ง€ ์•Š์Œ - - ๋งค์šฐ ์งง์Œ - - ์ž˜ ์•Œ๋ ค์ ธ ์žˆ์Œ + - ๊ณต๊ฐœ API์˜ ์ผ๋ถ€์ธ ๊ฒฝ์šฐ + - ๋น„๊ต์  ํฐ ๊ฒฝ์šฐ + - ์ง๊ด€์ ์ด์ง€ ์•Š์€ ๋กœ์ง์„ ๊ฐ€์ง„ ๊ฒฝ์šฐ -- docstring ์€ ์ง์ ‘ ํ•จ์ˆ˜์˜ ์ฝ”๋“œ๋ฅผ ์ฝ์–ด๋ณด์ง€ ์•Š๋”๋ผ๋„ ์ถฉ๋ถ„ํžˆ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ ํ•  ์ˆ˜ ์žˆ์„๋งŒํผ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- docstring์€ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ๋ฐฉ์‹์ด๋‚˜ ์‹œ๋ฉ˜ํ‹ฑ๋“ฑ์„ ๋ฐ˜๋“œ์‹œ ๊ธฐ์ˆ ํ•˜๋˜ ํ•จ์ˆ˜์˜ ์‚ฌ์šฉํ•จ์— ์žˆ์–ด ์˜ํ•ญ์„ ์ฃผ์ง€ ์•Š๋Š” ํ•œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์ƒ์„ธํ•œ ๊ตฌํ˜„๋ฐฉ๋ฒ•์€ ๊ธฐ์ˆ ํ•˜์ง€ ์•„๋‹ˆํ•ฉ๋‹ˆ๋‹ค -- ์˜ˆ๋ฅผ๋“ค์–ด ํ•œ ํ•จ์ˆ˜๊ฐ€ ๊ตฌ๋™๊ณผ์ •์—์„œ ์ธ์ž๋กœ ๋ฐ›์€ ๋ณ€์ˆ˜ ํ•˜๋‚˜๋ฅผ ๋ณ€ํ˜•์‹œํ‚จ๋‹ค๋ฉด ์ด๋Š” docstring์— ๊ธฐ์ˆ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์ด์™ธ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ๊ณผ ์ƒ๊ด€์ด ์—†๋Š” ์ž์ž˜ํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ ํ•ญ๋ชฉ๋“ค์€ ํ•จ์ˆ˜ ๋‚ด docstring ๋ณด๋‹จ ์ฃผ์„์œผ๋กœ ๊ธฐ๋กํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค -- docstring ์€ (`"""Fetches rows from a Bigtable."""`) ์ฒ˜๋Ÿผ _์„ค๋ช…์กฐ_ ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ์•ผ ํ•˜๋ฉฐ (`"""Fetch rows from a Bigtable."""`) ์ฒ˜๋Ÿผ _๋ช…๋ น์กฐ_ ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- docstring ์€ ํ•จ์ˆ˜์˜ ๊ตฌํ˜„๋ฐฉ์‹์ด ์•„๋‹Œ ํ˜ธ์ถœ ๋ฐฉ๋ฒ•๊ณผ ์˜๋ฏธ๋ฅผ ๊ธฐ์ˆ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋ณต์žกํ•œ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ docstring ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์ฝ”๋“œ ํ•œ ์ค„๋งˆ๋‹ค ์ฃผ์„์„ ์ฒจ๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ๋” ์•Œ๋งž์Šต๋‹ˆ๋‹ค. +- docstring์€ ํ•จ์ˆ˜์˜ ์ฝ”๋“œ๋ฅผ ์ฝ์ง€ ์•Š๊ณ ๋„ ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์„ ๋งŒํผ ์ถฉ๋ถ„ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- docstring์€ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ ๊ตฌ๋ฌธ๊ณผ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•ด์•ผ ํ•˜๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ ํฌํ•จํ•˜์ง€ ์•Š์•„์•ผ ํ•˜์ง€๋งŒ, ์ด๋Ÿฌํ•œ ์„ธ๋ถ€ ์‚ฌํ•ญ์ด ํ•จ์ˆ˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ์ค‘์š”ํ•˜๋‹ค๋ฉด ์˜ˆ์™ธ์ž…๋‹ˆ๋‹ค. +- ์˜ˆ๋ฅผ ๋“ค์–ด, ์ธ์ž๋ฅผ ์‚ฌ์ด๋“œ ์ž„ํŽ™ํŠธ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜๋Š” ๊ทธ ์ ์„ docstring์— ๋ช…์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋‹ค๋ฅธ ๊ธฐ๋ณธ ๊ฐ์ฒด์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋Š” `"""See base class."""` ์ฒ˜๋Ÿผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ docstring ์— ์˜ค๋ฒ„๋ผ์ด๋“œ๋œ ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ์Œ์„ ์•Œ๋ ค์ฃผ๋Š” docstring ์„ ์ „๋‹ฌ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -- ๊ทธ ์ด์œ ๋Š” ๊ฐ™์€ ๋ฌธ์„œ๋ฅผ ์—ฌ๋Ÿฌ๊ณณ์—์„œ ๋ฐ˜๋ณตํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. -- ํ•˜์ง€๋งŒ ์˜ค๋ฒ„๋ผ์ด๋”ฉ๋œ ๋ฉ”์†Œ๋“œ๊ฐ€ ๊ธฐ์กด์˜ ๋ฉ”์†Œ๋“œ์™€ ํ™•์—ฐํ•˜๊ฒŒ ๋‹ค๋ฅธ ๋™์ž‘๋ฐฉ์‹์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ฑฐ๋‚˜ ์„ธ๋ถ€์ ์ธ ๋‚ด์šฉ(e.g., ์ž ์žฌ์ ์ธ ๋ถ€์ž‘์šฉ ๋“ฑ)์ด ์กด์žฌํ•œ๋‹ค๋ฉด ์ ์–ด๋„ ๊ทธ๋Ÿฌํ•œ ์ฐจ์ด์ ๋“ค์€ docstring ์„ ํ†ตํ•ด ๊ธฐ๋ก๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, ํ˜ธ์ถœ์ž์—๊ฒŒ ์ค‘์š”ํ•˜์ง€ ์•Š์€ ํ•จ์ˆ˜ ๊ตฌํ˜„์˜ ๋ฏธ๋ฌ˜ํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ ํ•จ์ˆ˜์˜ docstring๋ณด๋‹ค๋Š” ์ฝ”๋“œ ์˜†์— ์ฃผ์„์œผ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. +- docstring์€ ์„œ์ˆ ํ˜•(`"""Fetches rows from a Bigtable."""`) ๋˜๋Š” ๋ช…๋ นํ˜•(`"""Fetch rows from a Bigtable."""`) ์Šคํƒ€์ผ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ํŒŒ์ผ ๋‚ด์—์„œ ์Šคํƒ€์ผ์€ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- `@property` ์†์„ฑ์˜ docstring์€ ์†์„ฑ์ด๋‚˜ [ํ•จ์ˆ˜ ์ธ์ž](#doc-function-args)์˜ docstring๊ณผ ๊ฐ™์€ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (`"""The Bigtable path."""` ๋Œ€์‹ ์— `"""Returns the Bigtable path."""`). -- ๋‹ค๋งŒ ํ•จ์ˆ˜์˜ ๋ช‡๊ฐ€์ง€ ํŠน์ • ๋ถ€๋ถ„๋“ค์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋ณ„๋„์˜ ํŠน๋ณ„์„น์…˜์œผ๋กœ ๊ธฐ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๊ฐ ์„น์…˜์€ ํ‘œ์ œ๋กœ ์‹œ์ž‘ํ•˜๋ฉฐ ์ฝœ๋ก ์œผ๋กœ ๋๋งบ์Šต๋‹ˆ๋‹ค. -- ๊ฐ ์„น์…˜์€ ํ‘œ์ œ๋ฅผ ์ œ์™ธํ•˜๊ณ  2์นธ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. +- ํ•จ์ˆ˜์˜ ํŠน์ • ์ธก๋ฉด์€ ์•„๋ž˜์— ๋‚˜์—ด๋œ ํŠน๋ณ„ํ•œ ์„น์…˜์—์„œ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๊ฐ ์„น์…˜์€ ์ฝœ๋ก ์œผ๋กœ ๋๋‚˜๋Š” ์ œ๋ชฉ ํ–‰์œผ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. +- ์ œ๋ชฉ์„ ์ œ์™ธํ•œ ๋ชจ๋“  ์„น์…˜์€ 2์นธ ๋˜๋Š” 4์นธ ๊ณต๋ฐฑ์˜ ๊ฑธ์ณ์„œ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์œ ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (ํŒŒ์ผ ๋‚ด์—์„œ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€). +- ํ•จ์ˆ˜์˜ ์ด๋ฆ„๊ณผ ์‹œ๊ทธ๋‹ˆ์ฒ˜๊ฐ€ ์ถฉ๋ถ„ํžˆ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์—ฌ ํ•œ ์ค„์˜ docstring์œผ๋กœ ์ ์ ˆํžˆ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ, ์ด๋Ÿฌํ•œ ์„น์…˜์€ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -437,12 +499,13 @@ ##### [_Returns:_ (์ œ๋„ˆ๋ ˆ์ดํ„ฐ์—๋Š” _Yields:_)](#doc-function-returns) -- ๋ฐ˜ํ™˜๊ฐ’์˜ ์ž๋ฃŒํ˜•๊ณผ ์˜๋ฏธ๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ•จ์ˆ˜๊ฐ€ None๋งŒ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋ฉด ์ด ์„น์…˜์€ ํ•„์š”์—†์Šต๋‹ˆ๋‹ค. -- ๋˜ํ•œ ๋งŒ์•ฝ docstring์ด Returns ๋‚˜ Yields๋กœ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜(e.g. `"""Returns row from Bigtable as a tuple of strings."""`) ์ถฉ๋ถ„ํ•œ ์„ค๋ช…์ด ์ œ๊ณต๋œ๋‹ค๋ฉด ์ƒ๋žต ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -- Tuple ๋ฐ˜ํ™˜ ๊ฐ’์„ ๊ฐœ๋ณ„ ์ด๋ฆ„์ด ์žˆ๋Š” ์—ฌ๋Ÿฌ ๋ฐ˜ํ™˜ ๊ฐ’์ธ ๊ฒƒ์ฒ˜๋Ÿผ ์ž์ฃผ ๋ฌธ์„œํ™”ํ•˜๋Š” 'NumPy style' ([example](http://numpy.org/doc/stable/reference/generated/numpy.linalg.qr.html))์„ ๋ชจ๋ฐฉํ•˜์ง€ ๋งˆ์„ธ์š”. (Tuple๋ฅผ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.) -- ๋Œ€์‹ , ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ๊ธฐ์ˆ ํ•˜์„ธ์š”. - - "Returns a tuple (mat_a, mat_b), where mat_a is ..., and ...". -- Docstring์˜ ๋ณด์กฐ ์ด๋ฆ„์€ ํ•จ์ˆ˜ ๋ณธ๋ฌธ์— ์‚ฌ์šฉ๋œ ๋‚ด๋ถ€ ์ด๋ฆ„๊ณผ ๋ฐ˜๋“œ์‹œ ์ผ์น˜ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. (ํ•ด๋‹น ์ด๋ฆ„์€ API์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.) +- ๋ฐ˜ํ™˜ ๊ฐ’์˜ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•˜๊ณ , ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์—์„œ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ํƒ€์ž… ์ •๋ณด๋„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ํ•จ์ˆ˜๊ฐ€ None๋งŒ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ, ์ด ์„น์…˜์€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- docstring์ด "Return", "Returns", "Yield", "Yields"๋กœ ์‹œ์ž‘ํ•˜๊ณ (e.g. `"""Returns row from Bigtable as a tuple of strings."""`), ์ฒซ ๋ฒˆ์งธ ๋ฌธ์žฅ์ด ๋ฐ˜ํ™˜ ๊ฐ’์„ ์„ค๋ช…ํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•  ๊ฒฝ์šฐ, ์ด ์„น์…˜์€ ์ƒ๋žต๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- ์ด์ „์˜ 'NumPy ์Šคํƒ€์ผ'์„ ๋ชจ๋ฐฉํ•˜์ง€ ๋งˆ์„ธ์š”. ([example](https://numpy.org/doc/1.24/reference/generated/numpy.linalg.qr.html)) ์ด ์Šคํƒ€์ผ์€ ์ข…์ข… ํŠœํ”Œ ๋ฐ˜ํ™˜ ๊ฐ’์„ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐœ๋ณ„ ๋ฐ˜ํ™˜ ๊ฐ’์ฒ˜๋Ÿผ ๊ฐ๊ฐ์˜ ์ด๋ฆ„์œผ๋กœ ๋ฌธ์„œํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค. (ํŠœํ”Œ์ด๋ผ๋Š” ์ ์„ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š๊ณ ) +- ๋Œ€์‹ , ๋ฐ˜ํ™˜ ๊ฐ’์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๋ช…ํ•˜์„ธ์š”: "Returns: A tuple (mat_a, mat_b), where mat_a is ..., and ...". +- docstring์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์„ค๋ช…์šฉ ์ด๋ฆ„์€ ํ•จ์ˆ˜ ๋ณธ๋ฌธ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋‚ด๋ถ€ ์ด๋ฆ„๊ณผ ๋ฐ˜๋“œ์‹œ ์ผ์น˜ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค (๋‚ด๋ถ€ ์ด๋ฆ„์€ API์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค) +- ํ•จ์ˆ˜๊ฐ€ `yield`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ(์ฆ‰, ์ œ๋„ˆ๋ ˆ์ดํ„ฐ์ธ ๊ฒฝ์šฐ), `Yields:` ์„น์…˜์—์„œ๋Š” ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋กœ ๋ฐ˜ํ™˜๋˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ, `next()`์— ์˜ํ•ด ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -453,10 +516,11 @@ - ๋ช…์‹œ๋œ API๊ฐ€ docstring์„ ์œ„๋ฐ˜ํ–ˆ์„ ๋  ๊ฒฝ์šฐ, ์˜ˆ์™ธ๋ฅผ ๋ฌธ์„œํ™”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. (์™œ๋ƒํ•˜๋ฉด ์ด๊ฒƒ์€ ์—ญ์„ค์ ์œผ๋กœ API์˜ API๋ฅผ ์œ„๋ฐ˜ํ•˜๋Š” ํ–‰๋™์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.) ```python - def fetch_smalltable_rows(table_handle: smalltable.Table, - keys: Sequence[Union[bytes, str]], - require_all_keys: bool = False, - ) -> Mapping[bytes, Tuple[str, ...]]: + def fetch_smalltable_rows( + table_handle: smalltable.Table, + keys: Sequence[bytes | str], + require_all_keys: bool = False, + ) -> Mapping[bytes, tuple[str, ...]]: """Fetches rows from a Smalltable. Retrieves rows pertaining to the given keys from the Table instance @@ -490,10 +554,11 @@ - ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ์ค„ ๋ฐ”๊ฟˆ์ด ์žˆ๋Š” `Args:`๋„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ```python - def fetch_smalltable_rows(table_handle: smalltable.Table, - keys: Sequence[Union[bytes, str]], - require_all_keys: bool = False, - ) -> Mapping[bytes, Tuple[str, ...]]: + def fetch_smalltable_rows( + table_handle: smalltable.Table, + keys: Sequence[bytes | str], + require_all_keys: bool = False, + ) -> Mapping[bytes, tuple[str, ...]]: """Fetches rows from a Smalltable. Retrieves rows pertaining to the given keys from the Table instance @@ -526,19 +591,51 @@ """ ``` + + + +##### 3.8.3.1 Overridden Methods + +- ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” [`@override`](https://typing-extensions.readthedocs.io/en/latest/#override) ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ(`typing_extensions` ๋˜๋Š” `typing` ๋ชจ๋“ˆ์—์„œ ์ œ๊ณต)๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ docstring์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- ๋‹จ, ์˜ค๋ฒ„๋ผ์ด๋”ฉ๋œ ๋ฉ”์„œ๋“œ์˜ ๋™์ž‘์ด ๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ์˜ ๊ณ„์•ฝ์„ ์‹ค์งˆ์ ์œผ๋กœ ๊ฐœ์„ ํ•˜๊ฑฐ๋‚˜, ์ถ”๊ฐ€์ ์ธ ์‚ฌ์ด๋“œ ์ž„ํŽ™ํŠธ ๋“ฑ์„ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š”, ๊ทธ๋Ÿฌํ•œ ์ฐจ์ด์ ์ด ์ตœ์†Œํ•œ ํฌํ•จ๋œ docstring์ด ์˜ค๋ฒ„๋ผ์ด๋”ฉ ๋ฉ”์„œ๋“œ์— ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + + ```python + from typing_extensions import override + class Parent: + def do_something(self): + """Parent method, includes docstring.""" + # ์ž์‹ ํด๋ž˜์Šค, ์˜ค๋ฒ„๋ผ์ด๋“œ๋กœ ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ๋ฉ”์„œ๋“œ. + class Child(Parent): + @override + def do_something(self): + pass + ``` + + ```python + # ์ž์‹ ํด๋ž˜์Šค์—์„œ @override ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ, docstring์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + class Child(Parent): + def do_something(self): + pass + # docstring์ด ๋‹จ์ˆœํ•œ ๊ฒฝ์šฐ, @override๋งŒ์œผ๋กœ๋„ ๋ฌธ์„œ๊ฐ€ ๊ธฐ๋ณธ ํด๋ž˜์Šค์— ์žˆ์Œ์„ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + class Child(Parent): + @override + def do_something(self): + """See base class.""" + ``` + #### 3.8.4 Classes - ํด๋ž˜์Šค๋Š” ์„ ์–ธ ๋ฐ”๋กœ ์•„๋ž˜์— ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์„ค๋ช…ํ•˜๋Š” docstring ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ๋งŒ์•ฝ ํด๋ž˜์Šค๊ฐ€ public attributes ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด [function's `Args`](#doc-function-args) ์„น์…˜๊ณผ ๊ฐ™์€ ํ˜•์‹์„ ์‚ฌ์šฉํ•ด `Attributes` ์„น์…˜์„ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- [properties](#properties)์„ ์ œ์™ธํ•œ ๊ณต๊ฐœ ์†์„ฑ์€ `Attributes` ์„น์…˜์—์„œ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•˜๋ฉฐ, [ํ•จ์ˆ˜์˜ `Args`](#doc-function-args) ์„น์…˜๊ณผ ๋™์ผํ•œ ํ˜•์‹์„ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ```python class SampleClass: """Summary of class here. - Longer class information.... - Longer class information.... + Longer class information... + Longer class information... Attributes: likes_spam: A boolean indicating if we like SPAM or not. @@ -546,14 +643,42 @@ class SampleClass: """ def __init__(self, likes_spam: bool = False): - """Inits SampleClass with blah.""" + """Initializes the instance based on spam preference. + Args: + likes_spam: Defines if instance exhibits this preference. + """ self.likes_spam = likes_spam self.eggs = 0 - def public_method(self): - """Performs operation blah.""" + @property + def butter_sticks(self) -> int: + """The number of butter sticks we have.""" ``` +- ๋ชจ๋“  ํด๋ž˜์Šค์˜ docstring์€ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฌด์—‡์„ ๋‚˜ํƒ€๋‚ด๋Š”์ง€๋ฅผ ์„ค๋ช…ํ•˜๋Š” ํ•œ ์ค„ ์š”์•ฝ์œผ๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” `Exception`์˜ ์„œ๋ธŒํด๋ž˜์Šค๋„ ์˜ˆ์™ธ๊ฐ€ ๋ฌด์—‡์„ ๋‚˜ํƒ€๋‚ด๋Š”์ง€๋ฅผ ์„ค๋ช…ํ•ด์•ผ ํ•˜๋ฉฐ, ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•ด์„œ๋Š” ์„ค๋ช…ํ•˜์ง€ ์•Š์•„์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ํด๋ž˜์Šค์˜ docstring์€ ํด๋ž˜์Šค๊ฐ€ ํด๋ž˜์Šค๋ผ๋Š” ๋“ฑ์˜ ๋ถˆํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. + +- ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ + + ```python + class CheeseShopAddress: + """The address of a cheese shop. + ... + """ + class OutOfCheeseError(Exception): + """No more cheese is available.""" + ``` + +- ๋ถ€์ ์ ˆํ•œ ์˜ˆ + + ```python + class CheeseShopAddress: + """Class that describes the address of a cheese shop. + ... + """ + class OutOfCheeseError(Exception): + """Raised when no more cheese is available.""" + ``` + @@ -604,25 +729,24 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. ### 3.10 Strings - ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋ชจ๋‘ ๋ฌธ์ž์—ด์ธ ๊ฒฝ์šฐ์—๋„ [f-string](https://docs.python.org/3/reference/lexical_analysis.html#f-strings), `format` ๋ฉ”์†Œ๋“œ๋‚˜ `%` ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํฌ๋ฉ”ํŒ…ํ•˜์„ธ์š”. -- ๋ฌผ๋ก  `+` ๋‚˜ `%` (๋˜๋Š” `format`) ๋ฅผ ์–ธ์ œ ์‚ฌ์šฉํ• ์ง€๋Š” ๊ฐœ๋ฐœ์ž์˜ ํŒ๋‹จ์— ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. -- ๋ฌธ์ž์—ด์„ ํ•ฉ์น˜๊ธฐ ์œ„ํ•ด `%` ๋˜๋Š” `format`์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. +- ๋ฌธ์ž์—ด ํฌ๋งทํŒ… ์˜ต์…˜ ์‚ฌ์ด์—์„œ ์ตœ์ƒ์˜ ํŒ๋‹จ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- `+`๋ฅผ ์‚ฌ์šฉํ•œ ๋‹จ์ผ join์€ ๊ดœ์ฐฎ์ง€๋งŒ, `+`๋ฅผ ์‚ฌ์šฉํ•œ ํฌ๋งทํŒ…์€ ํ”ผํ•˜์„ธ์š”. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - x = a + b + x = f'name: {name}; score: {n}' x = '%s, %s!' % (imperative, expletive) x = '{}, {}'.format(first, second) x = 'name: %s; score: %d' % (name, n) + x = 'name: %(name)s; score: %(score)d' % {'name':name, 'score':n} x = 'name: {}; score: {}'.format(name, n) - x = f'name: {name}; score: {n}' + x = a + b ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ ```python - x = '%s%s' % (a, b) # use + in this case - x = '{}{}'.format(a, b) # use + in this case x = first + ', ' + second x = 'name: ' + name + '; score: ' + str(n) ``` @@ -710,6 +834,9 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. will collapse common leading spaces in each line.""") ``` +- ์—ฌ๊ธฐ์„œ ๋ฐฑ์Šฌ๋ž˜์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ [๋ช…์‹œ์ ์ธ ์ค„ ์ด์–ด์“ฐ๊ธฐ](#line-length)์— ๋Œ€ํ•œ ๊ธˆ์ง€๋ฅผ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- ์ด ๊ฒฝ์šฐ, ๋ฐฑ์Šฌ๋ž˜์‹œ๋Š” ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์—์„œ [์ค„๋ฐ”๊ฟˆ์„ ์ด์Šค์ผ€์ดํ”„](https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals)ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + #### 3.10.1 Logging @@ -760,7 +887,7 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. ```python ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ: if not 0 <= p <= 1: - raise ValueError(f'Not a probability: {p!r}') + raise ValueError(f'Not a probability: {p=}') try: os.rmdir(workdir) except OSError as error: @@ -771,7 +898,7 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. ```python ์ž˜๋ชป๋œ ์˜ˆ: if p < 0 or p > 1: # PROBLEM: also false for float('nan')! - raise ValueError(f'Not a probability: {p!r}') + raise ValueError(f'Not a probability: {p=}') try: os.rmdir(workdir) except OSError: @@ -846,33 +973,44 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. - ์ž„์‹œ์ , ์ž ์‹œ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์ฝ”๋“œ ๋˜๋Š” ์ข‹๊ธฐ๋Š” ํ•˜์ง€๋งŒ ์™„๋ฒฝํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ `TODO` ์ฃผ์„์„ ์‚ฌ์šฉํ•˜์„ธ์š”. -- `TODO` ์ฃผ์„์€ ๋Œ€๋ฌธ์ž๋กœ ๋˜์–ด์žˆ๋Š” `TODO` ๋ฌธ๊ตฌ๋กœ ์‹œ์ž‘ํ•˜๋ฉฐ ํ•ด๋‹น ์ฝ”๋“œ์— ๋Œ€ํ•œ ๊ฐ€์žฅ ๋†’์€ ์ดํ•ด๋„๋ฅผ ๊ฐ€์ง„ ์ธ๋ฌผ์˜ ์ด๋ฆ„, ์ด๋ฉ”์ผ ์ฃผ์†Œ ๋˜๋Š” ๋‹ค๋ฅธ ์‹ ์›๊ตฌ๋ถ„ ๋ฌธ๊ตฌ๋ฅผ ๊ด„ํ˜ธ์•ˆ์— ๋„ฃ์–ด ํฌํ•จํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์ด๊ฒƒ ๋’ค์— ๋ฌด์—‡์„ ํ•ด์•ผํ•˜๋Š” ์ง€์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. +- `TODO` ์ฃผ์„์€ ๋ชจ๋‘ ๋Œ€๋ฌธ์ž๋กœ ๋œ `TODO`๋กœ ์‹œ์ž‘ํ•˜๊ณ , ๋‹ค์Œ์— ์ฝœ๋ก ์„ ๋ถ™์ด๋ฉฐ, ๋งฅ๋ฝ์ด ํฌํ•จ๋œ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ๋งํฌ(์ด์ƒ์ ์œผ๋กœ๋Š” ๋ฒ„๊ทธ ์ฐธ์กฐ)๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ๋ฒ„๊ทธ ์ฐธ์กฐ๊ฐ€ ์„ ํ˜ธ๋ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋ฒ„๊ทธ๋Š” ์ถ”์ ๋˜๋ฉฐ ํ›„์† ๋Œ“๊ธ€์ด ๋‹ฌ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +- ์ด ๋ฌธ๋งฅ ๋‹ค์Œ์— ํ•˜์ดํ”ˆ `-`์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์„ค๋ช… ๋ฌธ์ž์—ด์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”.. +- ๋ชฉ์ ์€ ์ผ๊ด€๋œ `TODO` ํ˜•์‹์„ ์œ ์ง€ํ•˜์—ฌ, ๋” ๋งŽ์€ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. -- ๋ชฉ์ ์€ `TODO`๊ฐ€ ์ผ๊ด€๋œ ํ˜•์‹์„ ์ด์šฉํ•˜์—ฌ ์ถ”ํ›„ ํ•„์š”ํ•œ ์„ธ๋ถ€์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. -- `TODO` ๋Š” ๋ณธ์ธ์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ฒ ๋‹ค๋Š” ์•ฝ์†์ด ์•„๋‹™๋‹ˆ๋‹ค. -- ๋”ฐ๋ผ์„œ `TODO` ๋ฅผ ๋งŒ๋“œ์…จ๋‹ค๋ฉด ๊ฑฐ์˜ ํ•ญ์ƒ ์ž‘์„ฑํ•œ ๋ณธ์ธ์˜ ์ด๋ฆ„์ด ๋“ค์–ด๊ฐ€์•ผ ํ•ฉ๋‹ˆ๋‹ค. + ```python + # TODO: crbug.com/192795 - Investigate cpufreq optimizations. + ``` -```python -# TODO(kl@gmail.com): Use a "*" here for string repetition. -# TODO(Zeke) Change this to use relations. -``` +- ์ด์ „ ์Šคํƒ€์ผ๋กœ, ์˜ˆ์ „์—๋Š” ๊ถŒ์žฅ๋˜์—ˆ์ง€๋งŒ ์ƒˆ๋กœ์šด ์ฝ”๋“œ์—์„œ๋Š” ์‚ฌ์šฉ์ด ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -- ๋งŒ์•ฝ ์ž‘์„ฑํ•œ `TODO` ๊ฐ€ "์ถ”ํ›„ ๋ฌด์—‡์„ ์ง„ํ–‰ํ•  ๊ฒƒ" ์ด๋ผ๋Š” ํ˜•์‹์„ ๋‹ด๊ณ  ์žˆ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ("2009๋…„ 11์›”๊นŒ์ง€") ์™€ ๊ฐ™์€ ๊ตฌ์ฒด์ ์ธ ๊ธฐ๊ฐ„์ด๋‚˜ ("๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ๊ฐ€ XML ์š”์ฒญ์„ ํ•ด๊ฒฐ ํ• ์ˆ˜ ์žˆ์„๋•Œ ์ด ์ฝ”๋“œ ์‚ญ์ œ") ์ฒ˜๋Ÿผ ๋ชฉ์ ์„ ํฌํ•จํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. + ```python + # TODO(crbug.com/192795): Investigate cpufreq optimizations. + # TODO(yourusername): Use a "\*" here for concatenation operator. + ``` + +- ๋ฌธ๋งฅ์œผ๋กœ ๊ฐœ์ธ์ด๋‚˜ ํŒ€์„ ์ฐธ์กฐํ•˜๋Š” TODO๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜์„ธ์š”. + + ```python + # TODO: @yourusername - File an issue and use a '*' for repetition. + ``` + +- `TODO`๊ฐ€ "๋ฏธ๋ž˜์˜ ์–ด๋Š ์‹œ์ ์— ๋ฌด์—‡์„ ํ•ด์•ผ ํ•œ๋‹ค"๋Š” ํ˜•์‹์ด๋ผ๋ฉด, ๋ฏธ๋ž˜์˜ ์ฝ”๋“œ ์œ ์ง€ ๊ด€๋ฆฌ์ž๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งค์šฐ ๊ตฌ์ฒด์ ์ธ ๋‚ ์งœ("2009๋…„ 11์›”๊นŒ์ง€")๋‚˜ ์‚ฌ๊ฑด("๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ๊ฐ€ XML ์š”์ฒญ์„ ํ•ด๊ฒฐ ํ• ์ˆ˜ ์žˆ์„๋•Œ ์ด ์ฝ”๋“œ ์‚ญ์ œ")์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์ด์Šˆ๋Š” ์ด๋ฅผ ์ถ”์ ํ•˜๋Š” ๋ฐ ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค. --- ### 3.13 import ํ˜•์‹ -- imports๋Š” ๊ฐœ๋ณ„์ ์ธ ๋ผ์ธ์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค; [`typing` imports์— ๋Œ€ํ•œ ์˜ˆ์™ธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.](#s3.19.12-imports). +- imports๋Š” ๊ฐœ๋ณ„์ ์ธ ๋ผ์ธ์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค; [`typing` ๊ทธ๋ฆฌ๊ณ  `collections.abc` imports์— ๋Œ€ํ•œ ์˜ˆ์™ธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.](#s3.19.12-imports). - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python import os import sys - from typing import Mapping, Sequence + from typing import Any, NewType ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ @@ -884,7 +1022,15 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. - import๋Š” ๋ชจ๋“ˆ์˜ ์ฃผ์„ ๊ณผ docstring ๋ฐ”๋กœ ๋‹ค์Œ, ๋ชจ๋“ˆ ์ „์—ญ ๋ฐ ์ƒ์ˆ˜ ๋ฐ”๋กœ ์•ž ํŒŒ์ผ์˜ ๋งจ ์œ„์— ๋ฐฐ์น˜๋ฉ๋‹ˆ๋‹ค. - import๋Š” ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๊ฒƒ ๋ถ€ํ„ฐ ์ตœ์†Œํ•œ์˜ ์ผ๋ฐ˜์ ์ธ ๊ฒƒ๋“ค๊นŒ์ง€ ๋ฌถ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -1. ํŒŒ์ด์ฌ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ +1. Python์˜ **future** import ๋ฌธ + + ```python + from __future__ import annotations + ``` + + ์ž์„ธํ•œ ๋‚ด์šฉ์€ [์œ„](#from-future-imports)๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. + +2. ํŒŒ์ด์ฌ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ - import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -892,7 +1038,7 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. import sys ``` -2. [third-party](https://pypi.org/) +3. [third-party](https://pypi.org/) - ๋ชจ๋“ˆ์ด๋‚˜ ํŒจํ‚ค์ง€์˜ import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -900,7 +1046,7 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. import tensorflow as tf ``` -3. Code repository +4. Code repository - ์„œ๋ธŒ ํŒจํ‚ค์ง€์˜ import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -908,7 +1054,7 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. from otherproject.ai import mind ``` -4. ๋™์ผํ•œ top ๋ ˆ๋ฒจ์— ์†ํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํŠน์ •์„ importํ•˜๋Š” ๊ฒƒ์€ **๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค** +5. ๋™์ผํ•œ top ๋ ˆ๋ฒจ์— ์†ํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํŠน์ •์„ importํ•˜๋Š” ๊ฒƒ์€ **๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค** - ์„œ๋ธŒ ํŒจํ‚ค์ง€์˜ ํŒŒ์ผ import ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @@ -1006,7 +1152,9 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. `global_var_name`, `instance_var_name`, `function_parameter_name`, -`local_var_name`. +`local_var_name`, +`query_proper_noun_for_thing`, +`send_acronym_via_https`. - ํ•จ์ˆ˜ ์ด๋ฆ„, ๋ณ€์ˆ˜ ์ด๋ฆ„, ๊ทธ๋ฆฌ๊ณ  ํŒŒ์ผ ์ด๋ฆ„์€ ์„ค๋ช…์ ์ด์—ฌ์•ผ ํ•˜๊ณ  ์•ฝ์–ด๋กœ ์ ๋Š” ์ผ์„ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ํŠนํžˆ ๋ชจํ˜ธํ•˜๊ฑฐ๋‚˜ ํ”„๋กœ์ ํŠธ์— ์ฐธ์—ฌํ•˜์ง€ ์•Š์€ ์‚ฌ๋žŒ๋“ค์ด ์ฝ์—ˆ์„ ๋•Œ ์ต์ˆ™ํ•˜์ง€ ์•Š์€ ์•ฝ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งˆ์„ธ์š”. ๊ทธ๋ฆฌ๊ณ  ์ ˆ๋Œ€ ๋‹จ์–ด์—์„œ ๊ธ€์ž๋ฅผ ์ง€์›Œ ์ค„์ด์ง€ ๋งˆ์„ธ์š”. @@ -1017,15 +1165,20 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. #### 3.16.1 ํ”ผํ•ด์•ผ ํ•  ์ด๋ฆ„ -1. ์•„๋ž˜์™€ ๊ฐ™์€ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•œ ๋‹จ์ผ ๊ธ€์ž๋Š” ํ”ผํ•ฉ๋‹ˆ๋‹ค. +- ์•„๋ž˜์™€ ๊ฐ™์€ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•œ ๋‹จ์ผ ๊ธ€์ž๋Š” ํ”ผํ•ฉ๋‹ˆ๋‹ค. + + - counters์ด๋‚˜ iterators์—์„œ ์‚ฌ์šฉํ•  ๋•Œ (์˜ˆ. `i`, `j`, `k`, `v` ๋“ฑ) + - `try/except`๋ฌธ์—์„œ ์˜ˆ์™ธ ์‹๋ณ„์ž๋กœ `e`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ + - with๋ฌธ์˜ ํŒŒ์ผ ํ•ธ๋“ค์—์„œ `f`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ + - ์ œ์•ฝ ์กฐ๊ฑด์ด ์—†๋Š” ๋น„๊ณต์‹์ ์ธ [type variables](#typing-type-var)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ (e.g., `_T = TypeVar("_T"), _P = ParamSpec("_P")`) -- counters์ด๋‚˜ iterators์—์„œ ์‚ฌ์šฉํ•  ๋•Œ (์˜ˆ. `i`, `j`, `k`, `v` ๋“ฑ) -- `try/except`๋ฌธ์—์„œ ์˜ˆ์™ธ ์‹๋ณ„์ž๋กœ `e`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ -- with๋ฌธ์˜ ํŒŒ์ผ ํ•ธ๋“ค์—์„œ `f`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋‹จ์ผ ๊ธ€์ž๋ฅผ ๋‚จ์šฉํ•˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋งํ•ด์„œ ์„œ์ˆ ์„ฑ์€ ์ด๋ฆ„์˜ ๊ฐ€์‹œ์„ฑ ๋ฒ”์œ„์— ๋น„๋ก€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `i`๋Š” 5ํ–‰ ์ฝ”๋“œ ๋ธ”๋ก์— ์ ํ•ฉํ•œ ์ด๋ฆ„์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ค‘์ฒฉ๋œ ์—ฌ๋Ÿฌ ๋ฒ”์œ„ ๋‚ด์—์„œ๋Š” ๋„ˆ๋ฌด ๋ชจํ˜ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + - package/module ์ด๋ฆ„์—์„œ dashes(`-`)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ - `__์ด์ค‘_์„ ํ–‰_๋ฐ_ํ›„ํ–‰_๋ฐ‘์ค„__` ์ด๋ฆ„์„ ์‚ฌ์šฉํ•  ๋•Œ (Python์—์„œ ์˜ˆ์•ฝ์–ด) + - ์›๋ณธ์— ์—†๋Š” ์ถ”๊ฐ€ ์„ค๋ช… : double leading and trailing underscore : (์•ž ๋’ค๋กœ \_๊ฐ€ 2๊ฐœ์”ฉ ์žˆ๋Š”๊ฒƒ e.g **name**, **init**) + - ๊ณต๊ฒฉ์ ์ธ ๋‹จ์–ด - ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ณ€์ˆ˜ ํƒ€์ž…์„ ํฌํ•จํ•˜๋Š” ์ด๋ฆ„ (์˜ˆ : `id_to_name_dict`) @@ -1037,16 +1190,20 @@ if i & (i-1) == 0: # True if i is 0 or a power of 2. - "Internal"๋Š” ๋ชจ๋“ˆ์˜ ๋‚ด๋ถ€ ๋˜๋Š” ํด๋ž˜์Šค ๋‚ด์—์„œ protected ๋˜๋Š” private๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. - ๋‹จ์ผ ๋ฐ‘์ค„(`_`)์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ชจ๋“ˆ ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜๋ฅผ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ง€์›์ด ์žˆ์Šต๋‹ˆ๋‹ค. (linters๋Š” ๋ณดํ˜ธ๋œ ๋ฉค๋ฒ„ ์ ‘๊ทผ์— ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.) +- ๋‹จ์ผ ์–ธ๋”์Šค์ฝ”์–ด(`_`)๋ฅผ ์ ‘๋‘์‚ฌ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ชจ๋“ˆ ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜ ๋ณดํ˜ธ๋ฅผ ์œ„ํ•œ ์ผ๋ถ€ ์ง€์›์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค (linters๊ฐ€ ๋ณดํ˜ธ๋œ ๋ฉค๋ฒ„ ์ ‘๊ทผ์„ ๊ฒฝ๊ณ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค). ๊ทธ๋Ÿฌ๋‚˜ ์œ ๋‹› ํ…Œ์ŠคํŠธ๊ฐ€ ํ…Œ์ŠคํŠธ ์ค‘์ธ ๋ชจ๋“ˆ์˜ ๋ณดํ˜ธ๋œ ์ƒ์ˆ˜์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์€ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. - ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋‚˜ ๋ฉ”์†Œ๋“œ์— ์ด์ค‘ ๋ฐ‘์ค„(`__` : dunder)์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ณ€์ˆ˜๋‚˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•ด๋‹น ํด๋ž˜์Šค์— ๋Œ€ํ•ด ํšจ๊ณผ์ ์œผ๋กœ private ๋ฉ๋‹ˆ๋‹ค. - ๊ฐ€๋…์„ฑ๊ณผ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ์„ฑ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ณ  _์‹ค์ œ๋กœ_ ๋น„๊ณต๊ฐœ๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. - ํ•˜๋‚˜์˜ ๋ฐ‘์ค„์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. - ๋ชจ๋“ˆ์— ๊ด€๋ จ ํด๋ž˜์Šค์™€ top-level ํ•จ์ˆ˜๋ฅผ ํ•จ๊ป˜ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. - ์ž๋ฐ”์™€๋Š” ๋‹ค๋ฅด๊ฒŒ ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ์— ๋Œ€ํ•ด ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋กœ ์ œํ•œ์„ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. - CapWords(๋‹จ์–ด์˜ ์ฒซ ๊ธ€์ž๋ฅผ ๋Œ€๋ฌธ์ž๋กœ ํ•˜๋Š” ๋ฐฉ์‹)์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์ด \_with_under.py ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ์†Œ๋ฌธ์ž๋กœ ํ•ฉ๋‹ˆ๋‹ค. + - ๋น„๋ก ๋ช‡๋ช‡ ์˜ค๋ž˜๋œ ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์ด CapWords.py์ผ์ง€๋ผ๋„ ์ด์ œ๋Š” ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์„ class์ด๋ฆ„์— ๋”ฐ๋ผ ์ง“๊ฒŒ ๋˜๋ฉด ํ˜ผ๋ž€์Šค๋Ÿฌ์šฐ๋ฏ€๋กœ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. (e.g "์ž ๊น๋งŒ, -- ๋‚ด๊ฐ€ `import StringIO`๋ฅผ ํ•œ๊ฑฐ์•ผ ์•„๋‹ˆ๋ฉด `from StringIO import StringIO`๋ฅผ ํ•œ๊ฑฐ์•ผ ?" ๊ฐ™์€ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.) -- ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ CapWord๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ "test"๋กœ ์‹œ์ž‘ํ•˜๋Š” _unittest_ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์— Undercore๊ฐ€ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - - ํ•œ ๊ฐ€์ง€ ๊ฐ€๋Šฅํ•œ ํŒจํ„ด์€ `test_`๋กœ, ์˜ˆ๋ฅผ ๋“ค์–ด `testPop_EmptyStack`๊ฐ™์€ ํŒจํ„ด์€ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. - - test ๋ฉ”์„œ๋“œ์— ์— ์ด๋ฆ„์„ ๋ถ™์ด๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•์€ ์—†์Šต๋‹ˆ๋‹ค. + +- ์ƒˆ๋กœ์šด ์œ ๋‹› ํ…Œ์ŠคํŠธ ํŒŒ์ผ์€ PEP 8์„ ์ค€์ˆ˜ํ•˜๋Š” ์†Œ๋ฌธ์ž์™€ ์–ธ๋”์Šค์ฝ”์–ด ๋ฐฉ์‹์˜ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. + - ์˜ˆ๋ฅผ ๋“ค์–ด, `test**`์™€ ๊ฐ™์€ ํ˜•์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + - ์ผ๊ด€์„ฑ์„ ์œ„ํ•ด(\*) ์ด์ „ ๋ชจ๋“ˆ์—์„œ CapWords ํ•จ์ˆ˜ ์ด๋ฆ„์„ ๋”ฐ๋ฅด๋Š” ๊ฒฝ์šฐ, `test`๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ด๋ฆ„์— ๋…ผ๋ฆฌ์  ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด ์–ธ๋”์Šค์ฝ”์–ด๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + - ํ•˜๋‚˜์˜ ๊ฐ€๋Šฅํ•œ ํŒจํ„ด์€ `test_`์ž…๋‹ˆ๋‹ค. @@ -1146,9 +1303,24 @@ if __name__ == '__main__': #### 3.19.1 ์ผ๋ฐ˜์ ์ธ ๊ทœ์น™ -- [PEP-484](https://www.python.org/dev/peps/pep-0484/)์„ ์ฝ์œผ์„ธ์š”. -- ๋ฉ”์„œ๋“œ์—์„œ๋Š” `self`, `cls`๋Š” Type์˜ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—์„œ๋งŒ ์ฃผ์„์„ ๋‹ฌ์•„์•ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ) `@classmethod def create(cls: Type[T]) -> T: return cls()` +- [PEP-484](https://peps.python.org/pep-0484/)์„ ์ฝ์œผ์„ธ์š”. + +- `self` ๋˜๋Š” `cls`์— ์ฃผ์„์„ ๋‹ฌ ํ•„์š”๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์—†์Šต๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ ํƒ€์ž… ์ •๋ณด๋ฅผ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ [`Self`](https://docs.python.org/3/library/typing.html#typing.Self)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + ```python + from typing import Self + class BaseClass: + @classmethod + def create(cls) -> Self: + ... + def difference(self, other: Self) -> float: + ... + ``` + +- ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, `__init__`์˜ ๋ฐ˜ํ™˜ ๊ฐ’์— ์ฃผ์„์„ ๋‹ฌ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค (์—ฌ๊ธฐ์„œ `None`๋งŒ ์œ ํšจํ•œ ์˜ต์…˜์ž…๋‹ˆ๋‹ค). + - ๋ชจ๋“  ๋ณ€์ˆ˜๋‚˜ ๋ฐ˜ํ™˜๋˜๋Š” Type์ด ์ •ํ•ด์ง€์ง€ ์•Š์•˜๋‹ค๋ฉด `Any`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + - ๋ชจ๋“ˆ์—์„œ ๋ชจ๋“  ํ•จ์ˆ˜์— ์ฃผ์„์„ ๋‹ฌ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. - Public API์—๋Š” ์ตœ์†Œํ•œ์˜ ์ฃผ์„์„ ๋‹ต๋‹ˆ๋‹ค. - ํŒ๋‹จ๋ ฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•œํŽธ์œผ๋กœ๋Š” ์•ˆ์ „์„ฑ๊ณผ ๋ช…ํ™•์„ฑ, ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ํ•œํŽธ์œผ๋กœ๋Š” ์œ ์—ฐ์„ฑ ์‚ฌ์ด์˜ ๊ท ํ˜•์„ ์ž˜ ์žก์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -1163,12 +1335,15 @@ if __name__ == '__main__': - ๊ธฐ์กด์˜ [๋“ค์—ฌ์“ฐ๊ธฐ](#s3.4-indentation) ๊ทœ์น™์„ ๋”ฐ๋ฅด์„ธ์š”. - ์ฃผ์„์ฒ˜๋ฆฌํ•˜๊ณ ๋‚˜์„œ ๋งŽ์€ ํ•จ์ˆ˜๋Š” "ํ•œ ์ค„์— ํ•˜๋‚˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ"๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +- ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ๋ณ„๋„์˜ ์ค„์— ํ‘œ์‹œ๋˜๋„๋ก ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด, ๋งˆ์ง€๋ง‰ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋’ค์— ์‰ผํ‘œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python - def my_method(self, - first_var: int, - second_var: Foo, - third_var: Optional[Bar]) -> int: + def my_method( + self, + first_var: int, + second_var: Foo, + third_var: Bar | None, + ) -> int: ... ``` @@ -1180,23 +1355,25 @@ if __name__ == '__main__': ``` - ํ•จ์ˆ˜ ์ด๋ฆ„, ๋งˆ์ง€๋ง‰ ๋งค๊ฐœ ๋ณ€์ˆ˜ ๋ฐ ๋ฆฌํ„ด Type์˜ ์กฐํ•ฉ์ด ๋„ˆ๋ฌด ๊ธธ๋ฉด ์ƒˆ ํ–‰์—์„œ 4๋งŒํผ ๋“ค์—ฌ ์“ฐ๊ธฐ๋ฉ๋‹ˆ๋‹ค. +- ์ค„ ๋ฐ”๊ฟˆ์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๋ณ„๋„์˜ ์ค„์— ๋ฐฐ์น˜ํ•˜๊ณ , ๋‹ซ๋Š” ๊ด„ํ˜ธ๋ฅผ `def`์™€ ์ •๋ ฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ```python def my_method( - self, first_var: int) -> Tuple[MyLongType1, MyLongType1]: + self, + other_arg: MyLongType | None, + ) -> tuple[MyLongType1, MyLongType1]: ... ``` -๋ฆฌํ„ด ์œ ํ˜•์ด ๋งˆ์ง€๋ง‰ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๊ฐ™์€ ๋ผ์ธ์— ๋งž์ง€ ์•Š์„ ๊ฒฝ์šฐ, ์„ ํ˜ธ๋˜๋Š” ๋ฐฉ๋ฒ•์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ 4๋งŒํผ ์ƒˆ ๋ผ์ธ์— ๋“ค์—ฌ์“ฐ๊ณ  ๋‹ซํžˆ๋Š” ๊ด„ํ˜ธ๋ฅผ "def"์™€ ์ •๋ ฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค. +- ์„ ํƒ์ ์œผ๋กœ, ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๋งˆ์ง€๋ง‰ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๊ฐ™์€ ์ค„์— ๋ฐฐ์น˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -- ๋ฐ˜ํ™˜ Type์ด ๋งˆ์ง€๋ง‰ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๊ฐ™์€ ์ค„์ด ์•„๋‹ ๋•Œ, ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ 4๋งŒํผ ์ƒˆ ๋ผ์ธ์— ๋“ค์—ฌ์“ฐ๊ณ  ๋‹ซํžˆ๋Š” ๊ด„ํ˜ธ๋ฅผ `def`์™€ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค. - - - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ + - ๊ดœ์ฐฎ์€ ์˜ˆ ```python def my_method( - self, **kw_args: Optional[MyLongType] - ) -> Dict[OtherLongType, MyLongType]: + self, + first_var: int, + second_var: int) -> dict[OtherLongType, MyLongType]: ... ``` @@ -1206,8 +1383,8 @@ if __name__ == '__main__': ```python def my_method(self, - **kw_args: Optional[MyLongType] - ) -> Dict[OtherLongType, MyLongType]: + other_arg: MyLongType | None, + ) -> dict[OtherLongType, MyLongType]: ... ``` @@ -1217,10 +1394,11 @@ if __name__ == '__main__': ```python def my_method( self, - first_var: Tuple[List[MyLongType1], - List[MyLongType2]], - second_var: List[Dict[ - MyLongType3, MyLongType4]]) -> None: + first_var: tuple[list[MyLongType1], + list[MyLongType2]], + second_var: list[dict[ + MyLongType3, MyLongType4]], + ) -> None: ... ``` @@ -1251,23 +1429,34 @@ if __name__ == '__main__': #### 3.19.3 ์ „๋ฐฉ์„ ์–ธ -- ์•„์ง ์ •์˜๋˜์ง€ ์•Š์€ ๋™์ผํ•œ ๋ชจ๋“ˆ์˜ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ(์˜ˆ, ํด๋ž˜์Šค ์„ ์–ธ ๋‚ด์— ํด๋ž˜์Šค๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋˜๋Š” ์•„๋ž˜์— ์ •์˜๋œ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ) `from __future__ import annotations`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ์—๋Š” ์ฃผ์„์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํด๋ž˜์Šค ์ด๋ฆ„์— ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์•„์ง ์ •์˜๋˜์ง€ ์•Š์€ ํด๋ž˜์Šค ์ด๋ฆ„(์˜ˆ๋ฅผ ๋“ค์–ด, ํด๋ž˜์Šค ์„ ์–ธ ๋‚ด๋ถ€์—์„œ ํด๋ž˜์Šค ์ด๋ฆ„์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜ ์ฝ”๋“œ์—์„œ ๋‚˜์ค‘์— ์ •์˜๋œ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ)์„ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒฝ์šฐ, `from __future__ import annotations`๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํด๋ž˜์Šค ์ด๋ฆ„์„ ๋ฌธ์ž์—ด๋กœ ์‚ฌ์šฉํ•˜์„ธ์š”. -```python -from __future__ import annotations + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ -class MyClass: + ```python + from __future__ import annotations - def __init__(self, stack: Sequence[MyClass]) -> None: -``` + class MyClass: + def __init__(self, stack: Sequence[MyClass], item: OtherClass) -> None: + + class OtherClass: + ... + ``` + + ```python + class MyClass: + def __init__(self, stack: Sequence['MyClass'], item: 'OtherClass') -> None: + + class OtherClass: + ... + ``` #### 3.19.4 ๊ธฐ๋ณธ ๊ฐ’ - PEP-008์— ๋”ฐ๋ผ ์œ ํ˜• ์ฃผ์„๊ณผ ๊ธฐ๋ณธ๊ฐ’์ด ๋ชจ๋‘ ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฒฝ์šฐ "=" \_ only" ์ฃผ์œ„์— ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. -- [PEP-008](https://www.python.org/dev/peps/pep-0008/#other-recommendations)์— ๋”ฐ๋ผ Type ์ฃผ์„๊ณผ ๊ธฐ๋ณธ ๊ฐ’์ด ๋ชจ๋‘ ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฒฝ์šฐ `=` _only_ ์ฃผ์œ„์— ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์„ธ์š”, +- [PEP-008](https://peps.python.org/pep-0008/#other-recommendations)์— ๋”ฐ๋ผ Type ์ฃผ์„๊ณผ ๊ธฐ๋ณธ ๊ฐ’์ด ๋ชจ๋‘ ์žˆ๋Š” ์ธ์ˆ˜์˜ ๊ฒฝ์šฐ `=` _only_ ์ฃผ์œ„์— ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•˜์„ธ์š”, - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ @@ -1287,19 +1476,20 @@ class MyClass: #### 3.19.5 NoneType -- ํŒŒ์ด์ฌํ˜•์—์„œ ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ํผ์ŠคํŠธํด๋ž˜์Šคํ˜•์ด๋ฉฐ, ํƒ€์ดํ•‘์„ ์œ„ํ•ด ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ๋…ธ๋„คํƒ€์ž…(NoneType)์˜ ๋ณ„์นญ์ด๋‹ค. ๋…ผ์Ÿ์ด '์—†์Œ'์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค! ์œ ๋‹ˆ์˜จ(Union)์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋‹ค๋ฅธ ์œ ํ˜•์ด ํ•˜๋‚˜๋งŒ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” ์„ ํƒ์‚ฌํ•ญ(Option)์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. +- ํŒŒ์ด์ฌํ˜•์—์„œ ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ํผ์ŠคํŠธํด๋ž˜์Šคํ˜•์ด๋ฉฐ, ํƒ€์ดํ•‘์„ ์œ„ํ•ด ๋…ธ๋„คํƒ€์ž…(NoneType)์€ ๋…ธ๋„คํƒ€์ž…(NoneType)์˜ ๋ณ„์นญ์ด๋‹ค. +- ์ธ์ž๊ฐ€ `None`์ด ๋  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ, ์ด๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค! +- ์ƒˆ๋กœ์šด Python 3.10+ ์ฝ”๋“œ์—์„œ๋Š” `|` ์œ ๋‹ˆ์˜จ ํƒ€์ž… ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋˜๋ฉฐ, ์ด์ „์—๋Š” `Optional`๊ณผ `Union` ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -- ํŒŒ์ด์ฌ ํƒ€์ž… ์‹œ์Šคํ…œ์—์„œ `NoneType`์€ "first class" Type ์ด๋ฉฐ ์ž‘์„ฑ์„ ์œ„ํ•ด `None`์€ `NoneType`์˜ alias(๋ณ„์นญ)์ž…๋‹ˆ๋‹ค. ์ธ์ž๋Š” `None`์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์„ ์–ธ์„ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค! `Union`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‹ค๋ฅธ Type์ด ํ•˜๋‚˜๋งŒ ์žˆ๋Š” ๊ฒฝ์šฐ `Optional`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. - -- ์•”์‹œ์  `Optional` ๋Œ€์‹  ๋ช…์‹œ์  `Optional` ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. PEP 484 ์ด์ „ ๋ฒ„์ „์—์„œ๋Š” `a: Optional[str] = None` ๋Œ€์‹ ์— `a: str = None` ๋ฅผ ์„ ํ˜ธํ–ˆ์ง€๋งŒ ์ง€๊ธˆ์€ ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +- ์•”์‹œ์ ์ธ ๋Œ€์‹  ๋ช…์‹œ์ ์ธ `X | None`์„ ์‚ฌ์šฉํ•˜์„ธ์š”. +- ์ด์ „ ๋ฒ„์ „์˜ PEP 484์—์„œ๋Š” `a: str = None`์„ `a: str | None = None`์œผ๋กœ ํ•ด์„ํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ, ์ด์ œ๋Š” ์ด๊ฒƒ์ด ์„ ํ˜ธ๋˜๋Š” ๋™์ž‘์ด ์•„๋‹™๋‹ˆ๋‹ค. - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ ```python - def func(a: Optional[str], b: Optional[str] = None) -> str: - ... - def multiple_nullable_union(a: Union[None, str, int]) -> str: - ... + def modern_or_union(a: str | int | None, b: str | None = None) -> str: + ... + def union_optional(a: Union[str, int, None], b: Optional[str] = None) -> str: + ... ``` - ๋ถ€์ ์ ˆํ•œ ์˜ˆ @@ -1320,14 +1510,13 @@ class MyClass: - ์–ด๋ ค์šด Type์„ ๋ณ„์นญ์œผ๋กœ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณ„์นญ์€ CapWorded์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ณ„์นญ์ด ์ด ๋ชจ๋“ˆ์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” \_Private์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -- ์˜ˆ๋ฅผ ๋“ค์–ด Type๊ณผ ํ•จ๊ป˜ ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์ด ๋„ˆ๋ฌด ๊ธด ๊ฒฝ์šฐ - - ```python - _ShortName = module_with_long_name.TypeWithLongName - ComplexMap = Mapping[str, List[Tuple[int, int]]] - ``` +- TypeAlias ์ฃผ์„์€ ๋ฒ„์ „ 3.10 ์ด์ƒ์—์„œ๋งŒ ์ง€์›๋œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. -- ๋‹ค๋ฅธ ์˜ˆ๋กœ๋Š” ๋ณต์žกํ•œ ์ค‘์ฒฉ ์œ ํ˜•๊ณผ ํ•จ์ˆ˜์˜ ๋ณต์ˆ˜ ๋ฐ˜ํ™˜ ๋ณ€์ˆ˜(ํŠœํ”Œ)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. +```python +from typing import TypeAlias +_LossAndGradient: TypeAlias = tuple[tf.Tensor, tf.Tensor] +ComplexTFMap: TypeAlias = Mapping[str, _LossAndGradient] +``` @@ -1347,11 +1536,21 @@ class MyClass: #### 3.19.8 ๋‚ด๋ถ€ ๋ณ€์ˆ˜ ์ž‘์„ฑ -- ๋‚ด๋ถ€ ๋ณ€์ˆ˜๊ฐ€ ์œ ์ถ”ํ•˜๊ธฐ ์–ด๋ ต๊ฑฐ๋‚˜ ๋ถˆ๊ฐ€๋Šฅํ•œ ํƒ€์ž…์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ„๋„์˜ ์ฃผ์„์œผ๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + -```python -a = SomeUndecoratedFunction() # type: Foo -``` +- [_Annotated Assignments_](#annotated-assignments): ๋‚ด๋ถ€ ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์ถ”๋ก ํ•˜๊ธฐ ์–ด๋ ต๊ฑฐ๋‚˜ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ, ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ํ• ๋‹น์œผ๋กœ ํƒ€์ž…์„ ๋ช…์‹œํ•˜์„ธ์š”. ๋ณ€์ˆ˜ ์ด๋ฆ„๊ณผ ๊ฐ’ ์‚ฌ์ด์— ์ฝœ๋ก ๊ณผ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค (๊ธฐ๋ณธ๊ฐ’์ด ์žˆ๋Š” ํ•จ์ˆ˜ ์ธ์ˆ˜์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ). + + ```python + a: Foo = SomeUndecoratedFunction() + ``` + + + +- [_Type Comments_](#type-comments): ์ฝ”๋“œ๋ฒ ์ด์Šค์— ์—ฌ์ „ํžˆ ๋‚จ์•„ ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ (Python 3.6 ์ด์ „์—๋Š” ํ•„์š”ํ–ˆ์Œ), ๋” ์ด์ƒ `# type: ` ์ฃผ์„์„ ์ค„ ๋์— ์ถ”๊ฐ€ํ•˜์ง€ ๋งˆ์„ธ์š”. + + ```python + a = SomeUndecoratedFunction() # type: Foo + ``` @@ -1363,30 +1562,38 @@ a = SomeUndecoratedFunction() # type: Foo - ๋ฆฌ์ŠคํŠธ๋Š” ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. ```python -a = [1, 2, 3] # type: List[int] -b = (1, 2, 3) # type: Tuple[int, ...] -c = (1, "2", 3.5) # type: Tuple[int, str, float] +a: list[int] = [1, 2, 3] +b: tuple[int, ...] = (1, 2, 3) +c: tuple[int, str, float] = (1, "2", 3.5) ``` + -#### 3.19.10 TypeVar +#### 3.19.10 Type variables - ํŒŒ์ด์ฌํ˜• ์‹œ์Šคํ…œ์€ ์ผ๋ฐ˜์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ณต์žฅ ๊ธฐ๋Šฅ์ธ TypeVar๋Š” ํ”ํžˆ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. -- ํŒŒ์ด์„  Type์—๋Š” [generics](https://www.python.org/dev/peps/pep-0484/#generics)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. -- factory function `TypeVar`๋Š” ํ”ํžˆ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. +- ํŒŒ์ด์„  Type์—๋Š” [generics](https://peps.python.org/pep-0484/#generics)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. +- `TypeVar`์™€ `ParamSpec`๊ณผ ๊ฐ™์€ ํƒ€์ž… ๋ณ€์ˆ˜๋Š” ์ œ๋„ˆ๋ฆญ์„ ์‚ฌ์šฉํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ```python - from typing import List, TypeVar - T = TypeVar("T") + from collections.abc import Callable + from typing import ParamSpec, TypeVar + _P = ParamSpec("_P") + _T = TypeVar("_T") ... - def next(l: List[T]) -> T: - return l.pop() + def next(l: list[_T]) -> _T: + return l.pop() + def print_when_called(f: Callable[_P, _T]) -> Callable[_P, _T]: + def inner(*args: _P.args, **kwargs: _P.kwargs) -> _T: + print("Function was called") + return f(*args, **kwargs) + return inner ``` -- TypeVar๋Š” ๋ถ€์ž์—ฐ์Šค๋Ÿฌ์šธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +- `TypeVar`๋Š” ๋ถ€์ž์—ฐ์Šค๋Ÿฌ์šธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ```python AddableType = TypeVar("AddableType", int, float, str) @@ -1394,7 +1601,7 @@ c = (1, "2", 3.5) # type: Tuple[int, str, float] return a + b ``` -- `typing` ๋ชจ๋“ˆ์˜ ํ”ํžˆ ๋ฏธ๋ฆฌ ์ •์˜๋œ Type ๋ณ€์ˆ˜๋Š” `AnyStr`์ž…๋‹ˆ๋‹ค. `bytes`, `unicode`์ผ ์ˆ˜ ์žˆ๊ณ  ๋ชจ๋‘ ๊ฐ™์€ Type์ด์–ด์•ผ ํ•˜๋Š” ์—ฌ๋Ÿฌ ์ฃผ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +- `typing` ๋ชจ๋“ˆ์˜ ํ”ํžˆ ๋ฏธ๋ฆฌ ์ •์˜๋œ Type ๋ณ€์ˆ˜๋Š” `AnyStr`์ž…๋‹ˆ๋‹ค. `bytes`, `str`์ผ ์ˆ˜ ์žˆ๊ณ  ๋ชจ๋‘ ๊ฐ™์€ Type์ด์–ด์•ผ ํ•˜๋Š” ์—ฌ๋Ÿฌ ์ฃผ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ```python from typing import AnyStr @@ -1404,48 +1611,46 @@ c = (1, "2", 3.5) # type: Tuple[int, str, float] raise ValueError() ``` - - +- ํƒ€์ž… ๋ณ€์ˆ˜๋Š” ์„ค๋ช…์ ์ธ ์ด๋ฆ„์„ ๊ฐ€์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ, ๋‹ค์Œ ๋ชจ๋“  ๊ธฐ์ค€์„ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์˜ˆ์™ธ์ž…๋‹ˆ๋‹ค. -#### 3.19.11 ๋ฌธ์ž์—ด Type + - ์™ธ๋ถ€์—์„œ ๋ณด์ด์ง€ ์•Š๋Š” ๊ฒฝ์šฐ + - ์ œ์•ฝ ์กฐ๊ฑด์ด ์—†๋Š” ๊ฒฝ์šฐ -- String ์ฃผ์„์— ๋Œ€ํ•œ ์ ์ ˆํ•œ Type์€ ์ฝ”๋“œ์˜ ์šฉ๋„์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ -- `str`์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜์ง€๋งŒ `Text`๋„ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ `bytes`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. -- ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ(Python 2์—์„œ๋Š” `str` ๋˜๋Š” `unicode`, Python3์—์„œ๋Š” `str`)๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” Python 2 ํ˜ธํ™˜ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ `Text`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + ```python + _T = TypeVar("_T") + _P = ParamSpec("_P") + AddableType = TypeVar("AddableType", int, float, str) + AnyFunction = TypeVar("AnyFunction", bound=Callable) + ``` -```python -def deals_with_text_data_in_py3(x: str) -> str: - ... -def deals_with_binary_data(x: bytes) -> bytes: - ... -def py2_compatible_text_data_processor(x: Text) -> Text: - ... -``` + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ -- ์ผ๋ถ€ ํ”ํ•˜์ง€ ์•Š์€ Python2 ํ˜ธํ™˜์„ฑ ์‚ฌ๋ก€์—์„œ๋Š” `Text` ๋Œ€์‹  `str`์ด ์˜๋ฏธ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ Python2์™€ Python3 ๊ฐ„์— ๋ฐ˜ํ™˜ ์œ ํ˜•์ด ๋™์ผํ•˜์ง€ ์•Š์„ ๋•Œ ํ˜ธํ™˜์„ฑ์„ ๋•๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. -- Python3์—๋Š” `unicode`๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ ˆ๋Œ€ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. -- ์ด๋Ÿฌํ•œ ๋ถˆ์ผ์น˜๊ฐ€ ์กด์žฌํ•˜๋Š” ์ด์œ ๋Š” `str`์ด Python3์™€ Python2์—์„œ ๋‹ค๋ฅธ ์˜๋ฏธ๋ฅผ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + ```python + T = TypeVar("T") + P = ParamSpec("P") + _T = TypeVar("_T", int, float, str) + _F = TypeVar("_F", bound=Callable) + ``` -- ๋ถ€์ ์ ˆํ•œ ์˜ˆ + + + + -```python -def py2_code(x: str) -> unicode: - ... -``` +#### 3.19.11 ๋ฌธ์ž์—ด Type -If the type can be either bytes or text, use `Union`, with the appropriate text -type. +> ์ƒˆ๋กœ์šด ์ฝ”๋“œ์—์„œ๋Š” `typing.Text`๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. ์ด๋Š” Python 2/3 ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. -```python -from typing import Text, Union -... -def py3_only(x: Union[bytes, str]) -> Union[bytes, str]: - ... -def py2_compatible(x: Union[bytes, Text]) -> Union[bytes, Text]: - ... -``` +- ๋ฌธ์ž์—ด/ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์—๋Š” `str`์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ด์ง„ ๋ฐ์ดํ„ฐ์™€ ๊ด€๋ จ๋œ ์ฝ”๋“œ์—์„œ๋Š” `bytes`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + + ```python + def deals_with_text_data(x: str) -> str: + ... + def deals_with_binary_data(x: bytes) -> bytes: + ... + ``` - ํ•จ์ˆ˜์˜ ๋ชจ๋“  string Type์ด ํ•ญ์ƒ ๋™์ผํ•œ ๊ฒฝ์šฐ(์˜ˆ, ๋ฐ˜ํ™˜ Type์ด ์œ„์˜ ์ฝ”๋“œ์—์„œ ์ธ์ž Type๊ณผ ๋™์ผํ•œ ๊ฒฝ์šฐ) [AnyStr](#s3.19.10-type-var)๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -1456,19 +1661,31 @@ def py2_compatible(x: Union[bytes, Text]) -> Union[bytes, Text]: #### 3.19.12 Typing ์ถ”๊ฐ€ -- `typing` ๋ชจ๋“ˆ์˜ ํด๋ž˜์Šค๋Š” ํ•ญ์ƒ ํด๋ž˜์Šค ์ž์ฒด๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. `typing` ๋ชจ๋“ˆ์—์„œ ํ•œ ์ค„์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ํŠน์ • ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- `typing` ๋˜๋Š” `collections.abc` ๋ชจ๋“ˆ์—์„œ ์ •์  ๋ถ„์„ ๋ฐ ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ์‹ฌ๋ณผ(ํƒ€์ž…, ํ•จ์ˆ˜, ์ƒ์ˆ˜ ๋“ฑ)์€ ํ•ญ์ƒ ์‹ฌ๋ณผ ์ž์ฒด๋ฅผ ์ž„ํฌํŠธํ•˜์„ธ์š”. +- ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ผ๋ฐ˜์ ์ธ ์ฃผ์„์ด ๋” ๊ฐ„๊ฒฐํ•ด์ง€๊ณ , ์ „ ์„ธ๊ณ„์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํƒ€์ž… ์ฃผ์„ ๊ด€ํ–‰์— ๋งž์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- `typing` ๋ฐ `collections.abc` ๋ชจ๋“ˆ์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŠน์ • ์‹ฌ๋ณผ์„ ํ•œ ์ค„์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ž„ํฌํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python - from typing import Any, Dict, Optional + from collections.abc import Mapping, Sequence + from typing import Any, Generic, cast, TYPE_CHECKING ``` -- `typing`์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์ด ๋กœ์ปฌ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•œ๋‹ค๋Š” ์ ์—์„œ, `typing`์˜ ๋ชจ๋“  ์ด๋ฆ„์€ ํ‚ค์›Œ๋“œ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ทจ๊ธ‰๋˜์–ด์•ผ ํ•˜๋ฉฐ, typing์ด๋“  ์•„๋‹ˆ๋“  Python ์ฝ”๋“œ์— ์ •์˜๋˜์–ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค. -- ๋ชจ๋“ˆ์— ์žˆ๋Š” Type๊ณผ ๊ธฐ์กด ์ด๋ฆ„์ด ์ถฉ๋Œํ•˜๋Š” ๊ฒฝ์šฐ `import x as y`๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. +- ์ด ๋ฐฉ์‹์œผ๋กœ ์ž„ํฌํŠธํ•˜๋ฉด ๋กœ์ปฌ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ํ•ญ๋ชฉ์ด ์ถ”๊ฐ€๋˜๋ฏ€๋กœ, `typing` ๋˜๋Š” `collections.abc`์˜ ์ด๋ฆ„์€ ํ‚ค์›Œ๋“œ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ทจ๊ธ‰๋˜์–ด์•ผ ํ•˜๋ฉฐ, Python ์ฝ”๋“œ์—์„œ ์ •์˜๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์ž… ์—ฌ๋ถ€์™€ ๊ด€๊ณ„์—†์ด ๋ง์ž…๋‹ˆ๋‹ค. +- ๋ชจ๋“ˆ ๋‚ด์—์„œ ํƒ€์ž…๊ณผ ๊ธฐ์กด ์ด๋ฆ„ ๊ฐ„์— ์ถฉ๋Œ์ด ์žˆ๋Š” ๊ฒฝ์šฐ, `import x as y`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž„ํฌํŠธํ•˜์„ธ์š”. ```python from typing import Any as AnyType ``` +- ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ, ์ฃผ์„์œผ๋กœ ๋‚ด์žฅ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. +- Prefer to use built-in types as annotations where available. +- Python์€ [PEP-585](https://peps.python.org/pep-0585/)๋ฅผ ํ†ตํ•ด ๋งค๊ฐœํ˜• ์ปจํ…Œ์ด๋„ˆ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ ํƒ€์ž… ์ฃผ์„์„ ์ง€์›ํ•˜๋ฉฐ, ์ด๋Š” Python 3.9์—์„œ ๋„์ž…๋˜์—ˆ์Šต๋‹ˆ๋‹ค. + + ```python + def generate_foo_scores(foo: set[str]) -> list[float]: + ... + ``` + @@ -1509,7 +1726,7 @@ def f(x: "sketch.Sketch"): ... - ํ•˜์ง€๋งŒ ๊ธฐ์ˆ ์ ์œผ๋กœ Circular ์ข…์†์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๋‹ค์–‘ํ•œ ๋นŒ๋“œ ์‹œ์Šคํ…œ์€ ๋‹ค๋ฅธ ๋ชจ๋“ˆ์— ์˜์กดํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ ‡๊ฒŒ ํ•˜๋„๋ก ํ—ˆ๋ฝํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. - Circular ์ข…์†์„ ์ƒ์„ฑํ•˜๋Š” ๋ชจ๋“ˆ์„ `Any`๋กœ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค. - - ์˜๋ฏธ์žˆ๋Š” ์ด๋ฆ„์œผ๋กœ [alias](#s3.19.6-aliases)๋ฅผ ์ง€์ •ํ•˜๊ณ  ๋ชจ๋“ˆ์˜ ์‹ค์ œ Type ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์„ธ์š” (์–ด๋–ค ๊ฒƒ์˜ ์–ด๋–ค ์†์„ฑ์ธ Any). + - ์˜๋ฏธ์žˆ๋Š” ์ด๋ฆ„์œผ๋กœ [alias](#s3.19.6-aliases)๋ฅผ ์ง€์ •ํ•˜๊ณ  ๋ชจ๋“ˆ์˜ ์‹ค์ œ Type ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์„ธ์š” (`Any`์˜ ๋ชจ๋“  ์†์„ฑ์€ `Any`์ž…๋‹ˆ๋‹ค.). - Alias์˜ ์ •์˜๋Š” ๋งˆ์ง€๋ง‰์œผ๋กœ import์™€ ํ•œ ์ค„๋กœ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ```python @@ -1526,33 +1743,37 @@ def my_method(self, var: "some_mod.SomeType") -> None: #### 3.19.15 ์ผ๋ฐ˜ -- ์ฃผ์„์„ ๋‹ฌ๋•Œ, ์ผ๋ฐ˜ Type๋ฅผ ์ง€์ •ํ•˜๊ธฐ๋ฅผ ์„ ํ˜ธํ•˜๋ฉฐ ๊ทธ๋ ‡์ง€ [์•Š์„ ๋•Œ์—๋Š” `Any`๋กœ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค](https://www.python.org/dev/peps/pep-0484/#the-any-type). +- ์ฃผ์„์„ ๋‹ฌ๋•Œ, ์ผ๋ฐ˜ Type๋ฅผ ์ง€์ •ํ•˜๊ธฐ๋ฅผ ์„ ํ˜ธํ•˜๋ฉฐ ๊ทธ๋ ‡์ง€ [์•Š์„ ๋•Œ์—๋Š” `Any`๋กœ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค](https://peps.python.org/pep-0484/#the-any-type). -```python -def get_names(employee_ids: List[int]) -> Dict[int, Any]: - ... -``` + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ -```python -# ๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜ ๋ชจ๋‘ get_names(employee_ids: List[Any]) -> Dict[Any, Any] -def get_names(employee_ids: list) -> Dict: - ... + ```python + def get_names(employee_ids: Sequence[int]) -> Mapping[int, str]: + ... + ``` -def get_names(employee_ids: List) -> Dict: - ... -``` + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ + + ```python + # ์ด๋Š” get_names(employee_ids: Sequence[Any]) -> Mapping[Any, Any]๋กœ ํ•ด์„๋ฉ๋‹ˆ๋‹ค. + def get_names(employee_ids: Sequence) -> Mapping: + ``` - ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ ํ•ฉํ•œ Type์ด `Any`์ผ ๋•Œ, ๋ช…์‹œ์ ์œผ๋กœ ํ‘œํ˜„๋˜๋ฉฐ, ๋งŽ์€ ๊ฒฝ์šฐ์— [`TypeVar`](#s3.19.10-type-var)๊ฐ€ ๋” ์ ํ•ฉํ•  ์ˆ˜ ์žˆ์Œ์„ ๊ธฐ์–ตํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. -```python -def get_names(employee_ids: List[Any]) -> Dict[Any, str]: - """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" -``` + - ๋ถ€์ ์ ˆํ•œ ์˜ˆ -```python -T = TypeVar('T') -def get_names(employee_ids: List[T]) -> Dict[T, str]: - """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" -``` + ```python + def get_names(employee_ids: Sequence[Any]) -> Mapping[Any, str]: + """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" + ``` + + - ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ + + ```python + _T = TypeVar('_T') + def get_names(employee_ids: Sequence[_T]) -> Mapping[_T, str]: + """์ง์›์˜ ์•„์ด๋””๋ฅผ ์ด๋ฆ„๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" + ``` --- diff --git "a/Google Python Style Guide/4. \353\247\272\354\235\214\353\247\220/4.1 \353\247\272\354\235\214\353\247\220.md" "b/Google Python Style Guide/4. \353\247\272\354\235\214\353\247\220/4.1 \353\247\272\354\235\214\353\247\220.md" index 0413a7e..cb35dce 100644 --- "a/Google Python Style Guide/4. \353\247\272\354\235\214\353\247\220/4.1 \353\247\272\354\235\214\353\247\220.md" +++ "b/Google Python Style Guide/4. \353\247\272\354\235\214\353\247\220/4.1 \353\247\272\354\235\214\353\247\220.md" @@ -1,7 +1,12 @@

์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜์„ธ์š”

- ๋‹น์‹ ์ด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค๋ฉด ๋ช‡ ๋ถ„์„ ํˆฌ์žํ•ด์„œ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ณ  ์Šคํƒ€์ผ์„ ํŒŒ์•…ํ•˜์„ธ์š”. -- ๋งŒ์•ฝ ๋ชจ๋“  ์‚ฐ์ˆ  ์—ฐ์‚ฐ์ž์— ๊ณต๋ฐฑ์„ ๋„ฃ์—ˆ๋‹ค๋ฉด ๋‹น์‹ ๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ฃผ์„์ด hash marks(`#`)์œผ๋กœ ๋งŒ๋“  ๋ฐ•์Šค ์•ˆ์— ๋“ค์–ด์žˆ๋‹ค๋ฉด ๋‹น์‹ ์˜ ์ฃผ์„๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. +- ๊ทธ๋“ค์ด ์ธ๋ฑ์Šค ๋ณ€์ˆ˜ ์ด๋ฆ„์— `_idx` ์ ‘๋ฏธ์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ๋‹น์‹ ๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ฃผ์„์ด hash marks(`#`)์œผ๋กœ ๋งŒ๋“  ๋ฐ•์Šค ์•ˆ์— ๋“ค์–ด์žˆ๋‹ค๋ฉด ๋‹น์‹ ์˜ ์ฃผ์„๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. + - ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ๋ผ์ธ์˜ ์š”์ ์€ ์ฝ”๋”ฉ์—์„œ ๊ณตํ†ต๋œ ์–ดํˆฌ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋œ๋‹ค๋ฉด ์‚ฌ๋žŒ๋“ค์€ ๋‹น์‹ ์˜ ์ฝ”๋”ฉ ํ˜•์‹๋ณด๋‹ค๋Š” ๋‹น์‹ ์˜ ์ฝ”๋“œ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค - ์šฐ๋ฆฌ๋Š” ์—ฌ๊ธฐ์„œ ์‚ฌ๋žŒ๋“ค์ด ์–ดํœ˜๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋Š” ์„ธ๊ณ„์ ์ธ ์ฝ”๋”ฉ ์Šคํƒ€์ผ ๊ทœ์น™์„ ์ œ๊ณตํ•˜์ง€๋งŒ ๊ณ ์œ ์˜ ์Šคํƒ€์ผ๋„ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. -- ํŒŒ์ผ์— ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์„ ๋•Œ ์ด ์ฝ”๋“œ๊ฐ€ ๋‹ค๋ฅธ ์ฝ”๋“œ์™€ ๋น„๊ตํ•˜์—ฌ ํฌ๊ฒŒ ๋‹ฌ๋ผ ๋ณด์ด๋ฉด ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ์‚ฌ๋žŒ์˜ ์ž…์žฅ์—์„œ๋Š” ๋ฆฌ๋“ฌ์ด ๊นจ์ง‘๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์„ ์ฃผ์˜ํ•˜์„ธ์š”. +- ํŒŒ์ผ์— ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์„ ๋•Œ ์ด ์ฝ”๋“œ๊ฐ€ ๋‹ค๋ฅธ ์ฝ”๋“œ์™€ ๋น„๊ตํ•˜์—ฌ ํฌ๊ฒŒ ๋‹ฌ๋ผ ๋ณด์ด๋ฉด ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ์‚ฌ๋žŒ์˜ ์ž…์žฅ์—์„œ๋Š” ๋ฆฌ๋“ฌ์ด ๊นจ์ง‘๋‹ˆ๋‹ค. + +- ๊ทธ๋Ÿฌ๋‚˜ ์ผ๊ด€์„ฑ์—๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. +- ์ผ๊ด€์„ฑ์€ ์ฃผ๋กœ ์ง€์—ญ์ ์œผ๋กœ ์ ์šฉ๋˜๋ฉฐ, ์ „์—ญ ์Šคํƒ€์ผ์—์„œ ๋ช…์‹œ๋˜์ง€ ์•Š์€ ์„ ํƒ์— ๋” ๊ฐ•ํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. +- ์ผ๊ด€์„ฑ์„ ๊ตฌ์‹ ์Šคํƒ€์ผ์„ ๊ณ ์ˆ˜ํ•˜๋Š” ์ •๋‹นํ™”์˜ ๊ทผ๊ฑฐ๋กœ ์‚ผ๊ธฐ๋ณด๋‹ค๋Š” ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ์˜ ์žฅ์ ์ด๋‚˜ ์ฝ”๋“œ๋ฒ ์ด์Šค๊ฐ€ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ๋กœ ์ˆ˜๋ ดํ•˜๋Š” ๊ฒฝํ–ฅ์„ ๊ณ ๋ คํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. diff --git "a/Google Python Style Guide/4. \353\247\272\354\235\214\353\247\220/ReadMe.md" "b/Google Python Style Guide/4. \353\247\272\354\235\214\353\247\220/ReadMe.md" index c694fe0..cd576e7 100644 --- "a/Google Python Style Guide/4. \353\247\272\354\235\214\353\247\220/ReadMe.md" +++ "b/Google Python Style Guide/4. \353\247\272\354\235\214\353\247\220/ReadMe.md" @@ -1,9 +1,14 @@

์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜์„ธ์š”

- ๋‹น์‹ ์ด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค๋ฉด ๋ช‡ ๋ถ„์„ ํˆฌ์žํ•ด์„œ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ณ  ์Šคํƒ€์ผ์„ ํŒŒ์•…ํ•˜์„ธ์š”. -- ๋งŒ์•ฝ ๋ชจ๋“  ์‚ฐ์ˆ  ์—ฐ์‚ฐ์ž์— ๊ณต๋ฐฑ์„ ๋„ฃ์—ˆ๋‹ค๋ฉด ๋‹น์‹ ๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ฃผ์„์ด hash marks(`#`)์œผ๋กœ ๋งŒ๋“  ๋ฐ•์Šค ์•ˆ์— ๋“ค์–ด์žˆ๋‹ค๋ฉด ๋‹น์‹ ์˜ ์ฃผ์„๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. +- ๊ทธ๋“ค์ด ์ธ๋ฑ์Šค ๋ณ€์ˆ˜ ์ด๋ฆ„์— `_idx` ์ ‘๋ฏธ์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ๋‹น์‹ ๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ฃผ์„์ด hash marks(`#`)์œผ๋กœ ๋งŒ๋“  ๋ฐ•์Šค ์•ˆ์— ๋“ค์–ด์žˆ๋‹ค๋ฉด ๋‹น์‹ ์˜ ์ฃผ์„๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. + - ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ๋ผ์ธ์˜ ์š”์ ์€ ์ฝ”๋”ฉ์—์„œ ๊ณตํ†ต๋œ ์–ดํˆฌ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋œ๋‹ค๋ฉด ์‚ฌ๋žŒ๋“ค์€ ๋‹น์‹ ์˜ ์ฝ”๋”ฉ ํ˜•์‹๋ณด๋‹ค๋Š” ๋‹น์‹ ์˜ ์ฝ”๋“œ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค - ์šฐ๋ฆฌ๋Š” ์—ฌ๊ธฐ์„œ ์‚ฌ๋žŒ๋“ค์ด ์–ดํœ˜๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋Š” ์„ธ๊ณ„์ ์ธ ์ฝ”๋”ฉ ์Šคํƒ€์ผ ๊ทœ์น™์„ ์ œ๊ณตํ•˜์ง€๋งŒ ๊ณ ์œ ์˜ ์Šคํƒ€์ผ๋„ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. -- ํŒŒ์ผ์— ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์„ ๋•Œ ์ด ์ฝ”๋“œ๊ฐ€ ๋‹ค๋ฅธ ์ฝ”๋“œ์™€ ๋น„๊ตํ•˜์—ฌ ํฌ๊ฒŒ ๋‹ฌ๋ผ ๋ณด์ด๋ฉด ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ์‚ฌ๋žŒ์˜ ์ž…์žฅ์—์„œ๋Š” ๋ฆฌ๋“ฌ์ด ๊นจ์ง‘๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์„ ์ฃผ์˜ํ•˜์„ธ์š”. +- ํŒŒ์ผ์— ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์„ ๋•Œ ์ด ์ฝ”๋“œ๊ฐ€ ๋‹ค๋ฅธ ์ฝ”๋“œ์™€ ๋น„๊ตํ•˜์—ฌ ํฌ๊ฒŒ ๋‹ฌ๋ผ ๋ณด์ด๋ฉด ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ์‚ฌ๋žŒ์˜ ์ž…์žฅ์—์„œ๋Š” ๋ฆฌ๋“ฌ์ด ๊นจ์ง‘๋‹ˆ๋‹ค. + +- ๊ทธ๋Ÿฌ๋‚˜ ์ผ๊ด€์„ฑ์—๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. +- ์ผ๊ด€์„ฑ์€ ์ฃผ๋กœ ์ง€์—ญ์ ์œผ๋กœ ์ ์šฉ๋˜๋ฉฐ, ์ „์—ญ ์Šคํƒ€์ผ์—์„œ ๋ช…์‹œ๋˜์ง€ ์•Š์€ ์„ ํƒ์— ๋” ๊ฐ•ํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. +- ์ผ๊ด€์„ฑ์„ ๊ตฌ์‹ ์Šคํƒ€์ผ์„ ๊ณ ์ˆ˜ํ•˜๋Š” ์ •๋‹นํ™”์˜ ๊ทผ๊ฑฐ๋กœ ์‚ผ๊ธฐ๋ณด๋‹ค๋Š” ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ์˜ ์žฅ์ ์ด๋‚˜ ์ฝ”๋“œ๋ฒ ์ด์Šค๊ฐ€ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ๋กœ ์ˆ˜๋ ดํ•˜๋Š” ๊ฒฝํ–ฅ์„ ๊ณ ๋ คํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. --- diff --git a/Original.md b/Original.md index 09df969..74d3fab 100644 --- a/Original.md +++ b/Original.md @@ -17,7 +17,7 @@ See README.md for details. * [2.2 Imports](#s2.2-imports) * [2.3 Packages](#s2.3-packages) * [2.4 Exceptions](#s2.4-exceptions) - * [2.5 Global variables](#s2.5-global-variables) + * [2.5 Mutable Global State](#s2.5-global-variables) * [2.6 Nested/Local/Inner Classes and Functions](#s2.6-nested) * [2.7 Comprehensions & Generator Expressions](#s2.7-comprehensions) * [2.8 Default Iterators and Operators](#s2.8-default-iterators-and-operators) @@ -45,7 +45,9 @@ See README.md for details. * [3.8 Comments and Docstrings](#s3.8-comments-and-docstrings) + [3.8.1 Docstrings](#s3.8.1-comments-in-doc-strings) + [3.8.2 Modules](#s3.8.2-comments-in-modules) + + [3.8.2.1 Test modules](#s3.8.2.1-test-modules) + [3.8.3 Functions and Methods](#s3.8.3-functions-and-methods) + + [3.8.3.1 Overridden Methods](#s3.8.3.1-overridden-methods) + [3.8.4 Classes](#s3.8.4-comments-in-classes) + [3.8.5 Block and Inline Comments](#s3.8.5-block-and-inline-comments) + [3.8.6 Punctuation, Spelling, and Grammar](#s3.8.6-punctuation-spelling-and-grammar) @@ -74,7 +76,7 @@ See README.md for details. + [3.19.7 Ignoring Types](#s3.19.7-ignoring-types) + [3.19.8 Typing Variables](#s3.19.8-typing-variables) + [3.19.9 Tuples vs Lists](#s3.19.9-tuples-vs-lists) - + [3.19.10 TypeVars](#s3.19.10-typevars) + + [3.19.10 Type variables](#s3.19.10-typevars) + [3.19.11 String types](#s3.19.11-string-types) + [3.19.12 Imports For Typing](#s3.19.12-imports-for-typing) + [3.19.13 Conditional Imports](#s3.19.13-conditional-imports) @@ -96,7 +98,7 @@ of *dos and don'ts* for Python programs. To help you format code correctly, we've created a [settings file for Vim](google_python_style.vim). For Emacs, the default settings should be fine. -Many teams use the [yapf](https://github.com/google/yapf/) +Many teams use the [Black](https://github.com/psf/black) or [Pyink](https://github.com/google/pyink) auto-formatter to avoid arguing over formatting. @@ -160,7 +162,8 @@ Suppress warnings if they are inappropriate so that other issues are not hidden. To suppress warnings, you can set a line-level comment: ```python -dict = 'something awful' # Bad Idea... pylint: disable=redefined-builtin +def do_PUT(self): # WSGI name, so pylint: disable=invalid-name + ... ``` `pylint` @@ -184,7 +187,7 @@ pylint --list-msgs To get more information on a particular message, use: ```shell -pylint --help-msg=C6409 +pylint --help-msg=invalid-name ``` Prefer `pylint: disable` to the deprecated older form `pylint: disable-msg`. @@ -194,7 +197,7 @@ beginning of the function. Always include a comment explaining why you are deleting it. "Unused." is sufficient. For example: ```python -def viking_cafe_order(spam: str, beans: str, eggs: Optional[str] = None) -> str: +def viking_cafe_order(spam: str, beans: str, eggs: str | None = None) -> str: del beans, eggs # Unused by vikings. return spam + spam + spam ``` @@ -211,13 +214,8 @@ that the arguments are actually unused. ### 2.2 Imports -Use `import` statements for packages and modules only, not for individual -classes or functions. Classes imported from the -[typing module](#typing-imports), -[typing_extensions module](https://github.com/python/typing/tree/master/typing_extensions), -and redirects from the -[six.moves module](https://six.readthedocs.io/#module-six.moves) -are exempt from this rule. +Use `import` statements for packages and modules only, not for individual types, +classes, or functions. @@ -254,10 +252,16 @@ Module names can still collide. Some module names are inconveniently long. * Use `import x` for importing packages and modules. * Use `from x import y` where `x` is the package prefix and `y` is the module name with no prefix. -* Use `from x import y as z` if two modules named `y` are to be imported or if - `y` is an inconveniently long name. -* Use `import y as z` only when `z` is a standard abbreviation (e.g., `np` for - `numpy`). +* Use `from x import y as z` in any of the following circumstances: + - Two modules named `y` are to be imported. + - `y` conflicts with a top-level name defined in the current module. + - `y` conflicts with a common parameter name that is part of the public + API (e.g., `features`). + - `y` is an inconveniently long name. + - `y` is too generic in the context of your code (e.g., `from + storage.file_system import options as fs_options`). +* Use `import y as z` only when `z` is a standard abbreviation (e.g., `import + numpy as np`). For example the module `sound.effects.echo` may be imported as follows: @@ -271,6 +275,19 @@ Do not use relative names in imports. Even if the module is in the same package, use the full package name. This helps prevent unintentionally importing a package twice. + +##### 2.2.4.1 Exemptions + +Exemptions from this rule: + +* Symbols from the following modules are used to support static analysis and + type checking: + * [`typing` module](#typing-imports) + * [`collections.abc` module](#typing-imports) + * [`typing_extensions` module](https://github.com/python/typing_extensions/blob/main/README.md) +* Redirects from the + [six.moves module](https://six.readthedocs.io/#module-six.moves). + @@ -313,7 +330,7 @@ Yes: import absl.flags from doctor.who import jodie - FLAGS = absl.flags.FLAGS + _FOO = absl.flags.DEFINE_string(...) ``` ```python @@ -322,7 +339,7 @@ Yes: from absl import flags from doctor.who import jodie - FLAGS = flags.FLAGS + _FOO = flags.DEFINE_string(...) ``` *(assume this file lives in `doctor/who/` where `jodie.py` also exists)* @@ -337,7 +354,7 @@ No: The directory the main binary is located in should not be assumed to be in `sys.path` despite that happening in some environments. This being the case, -code should assume that `import jodie` refers to a third party or top level +code should assume that `import jodie` refers to a third-party or top-level package named `jodie`, not a local `jodie.py`. @@ -388,11 +405,15 @@ Exceptions must follow certain conditions: - Make use of built-in exception classes when it makes sense. For example, raise a `ValueError` to indicate a programming mistake like a violated - precondition (such as if you were passed a negative number but required a - positive one). Do not use `assert` statements for validating argument values - of a public API. `assert` is used to ensure internal correctness, not to - enforce correct usage nor to indicate that some unexpected event occurred. - If an exception is desired in the latter cases, use a raise statement. For + precondition, such as may happen when validating function arguments. + +- Do not use `assert` statements in place of conditionals or validating + preconditions. They must not be critical to the application logic. A litmus + test would be that the `assert` could be removed without breaking the code. + `assert` conditionals are + [not guaranteed](https://docs.python.org/3/reference/simple_stmts.html#the-assert-statement) + to be evaluated. For [pytest](https://pytest.org) based tests, `assert` is + okay and expected to verify expectations. For example: @@ -416,9 +437,10 @@ Exceptions must follow certain conditions: # guarantee this specific behavioral reaction to API misuse. raise ValueError(f'Min. port must be at least 1024, not {minimum}.') port = self._find_next_open_port(minimum) - if not port: + if port is None: raise ConnectionError( f'Could not connect to service on port {minimum} or higher.') + # The code does not depend on the result of this assert. assert port >= minimum, ( f'Unexpected port {port} when minimum was {minimum}.') return port @@ -436,8 +458,10 @@ Exceptions must follow certain conditions: The new minimum port. """ assert minimum >= 1024, 'Minimum port must be at least 1024.' + # The following code depends on the previous assert. port = self._find_next_open_port(minimum) assert port is not None + # The type checking of the return statement relies on the assert. return port ``` @@ -470,11 +494,13 @@ Exceptions must follow certain conditions: + + -### 2.5 Global variables +### 2.5 Mutable Global State -Avoid global variables. +Avoid mutable global state. @@ -482,7 +508,8 @@ Avoid global variables. #### 2.5.1 Definition -Variables that are declared at the module level or as class attributes. +Module-level values or class attributes that can get mutated during program +execution. @@ -498,8 +525,14 @@ Occasionally useful. #### 2.5.3 Cons -Has the potential to change module behavior during the import, because -assignments to global variables are done when the module is first imported. +* Breaks encapsulation: Such design can make it hard to achieve valid + objectives. For example, if global state is used to manage a database + connection, then connecting to two different databases at the same time + (such as for computing differences during a migration) becomes difficult. + Similar problems easily arise with global registries. + +* Has the potential to change module behavior during the import, because + assignments to global variables are done when the module is first imported. @@ -507,15 +540,20 @@ assignments to global variables are done when the module is first imported. #### 2.5.4 Decision -Avoid global variables. +Avoid mutable global state. -While they are technically variables, module-level constants are permitted and -encouraged. For example: `_MAX_HOLY_HANDGRENADE_COUNT = 3`. Constants must be -named using all caps with underscores. See [Naming](#s3.16-naming) below. +In those rare cases where using global state is warranted, mutable global +entities should be declared at the module level or as a class attribute and made +internal by prepending an `_` to the name. If necessary, external access to +mutable global state must be done through public functions or class methods. See +[Naming](#s3.16-naming) below. Please explain the design reasons why mutable +global state is being used in a comment or a doc linked to from a comment. -If needed, globals should be declared at the module level and made internal to -the module by prepending an `_` to the name. External access must be done -through public module-level functions. See [Naming](#s3.16-naming) below. +Module-level constants are permitted and encouraged. For example: +`_MAX_HOLY_HANDGRENADE_COUNT = 3` for an internal use constant or +`SIR_LANCELOTS_FAVORITE_COLOR = "blue"` for a public API constant. Constants +must be named using all caps with underscores. See [Naming](#s3.16-naming) +below. @@ -544,8 +582,8 @@ variables defined in enclosing scopes. Allows definition of utility classes and functions that are only used inside of a very limited scope. Very -[ADT](http://www.google.com/url?sa=D&q=http://en.wikipedia.org/wiki/Abstract_data_type)-y. -Commonly used for implementing decorators. +[ADT](https://en.wikipedia.org/wiki/Abstract_data_type)-y. Commonly used for +implementing decorators. @@ -612,20 +650,18 @@ Complicated comprehensions or generator expressions can be hard to read. #### 2.7.4 Decision -Okay to use for simple cases. Each portion must fit on one line: mapping -expression, `for` clause, filter expression. Multiple `for` clauses or filter -expressions are not permitted. Use loops instead when things get more -complicated. +Comprehensions are allowed, however multiple `for` clauses or filter expressions +are not permitted. Optimize for readability, not conciseness. ```python Yes: result = [mapping_expr for value in iterable if filter_expr] - result = [{'key': value} for value in iterable - if a_long_filter_expression(value)] - - result = [complicated_transform(x) - for x in iterable if predicate(x)] + result = [ + is_valid(metric={'key': value}) + for value in interesting_iterable + if a_longer_filter_expression(value) + ] descriptive_name = [ transform({'key': key, 'value': value}, color='black') @@ -635,36 +671,33 @@ Yes: result = [] for x in range(10): - for y in range(5): - if x * y > 10: - result.append((x, y)) - - return {x: complicated_transform(x) - for x in long_generator_function(parameter) - if x is not None} + for y in range(5): + if x * y > 10: + result.append((x, y)) + + return { + x: complicated_transform(x) + for x in long_generator_function(parameter) + if x is not None + } - squares_generator = (x**2 for x in range(10)) + return (x**2 for x in range(10)) unique_names = {user.name for user in users if user is not None} - - eat(jelly_bean for jelly_bean in jelly_beans - if jelly_bean.color == 'black') ``` ```python No: - result = [complicated_transform( - x, some_argument=x+1) - for x in iterable if predicate(x)] - result = [(x, y) for x in range(10) for y in range(5) if x * y > 10] - return ((x, y, z) - for x in range(5) - for y in range(5) - if x != y - for z in range(5) - if y != z) + return ( + (x, y, z) + for x in range(5) + for y in range(5) + if x != y + for z in range(5) + if y != z + ) ``` @@ -700,8 +733,8 @@ operators is generic. It can be used with any type that supports the operation. #### 2.8.3 Cons -You can't tell the type of objects by reading the method names (e.g. `has_key()` -means a dictionary). This is also an advantage. +You can't tell the type of objects by reading the method names (unless the +variable has type annotations). This is also an advantage. @@ -716,18 +749,14 @@ container while iterating over it. ```python Yes: for key in adict: ... - if key not in adict: ... if obj in alist: ... for line in afile: ... for k, v in adict.items(): ... - for k, v in six.iteritems(adict): ... ``` ```python No: for key in adict.keys(): ... - if not adict.has_key(key): ... for line in afile.readlines(): ... - for k, v in dict.iteritems(): ... ``` @@ -742,7 +771,7 @@ Use generators as needed. -#### 2.9 Definition +#### 2.9.1 Definition A generator function returns an iterator that yields a value each time it executes a yield statement. After it yields a value, the runtime state of the @@ -764,7 +793,8 @@ creates an entire list of values at once. #### 2.9.3 Cons -None. +Local variables in the generator will not be garbage collected until the +generator is either consumed to exhaustion or itself garbage collected. @@ -775,6 +805,11 @@ None. Fine. Use "Yields:" rather than "Returns:" in the docstring for generator functions. +If the generator manages an expensive resource, make sure to force the clean up. + +A good way to do the clean up is by wrapping the generator with a context +manager [PEP-0533](https://peps.python.org/pep-0533/). + @@ -816,8 +851,8 @@ function may only contain an expression. #### 2.10.4 Decision -Okay to use them for one-liners. If the code inside the lambda function is -longer than 60-80 chars, it's probably better to define it as a regular +Lambdas are allowed. If the code inside the lambda function spans multiple lines +or is longer than 60-80 chars, it might be better to define it as a regular [nested function](#lexical-scoping). For common operations like multiplication, use the functions from the `operator` @@ -947,21 +982,24 @@ definition. Yes: def foo(a, b=None): if b is None: b = [] -Yes: def foo(a, b: Optional[Sequence] = None): +Yes: def foo(a, b: Sequence | None = None): if b is None: b = [] -Yes: def foo(a, b: Sequence = ()): # Empty tuple OK since tuples are immutable +Yes: def foo(a, b: Sequence = ()): # Empty tuple OK since tuples are immutable. ... ``` ```python +from absl import flags +_FOO = flags.DEFINE_string(...) + No: def foo(a, b=[]): ... -No: def foo(a, b=time.time()): # The time the module was loaded??? +No: def foo(a, b=time.time()): # Is `b` supposed to represent when this module was loaded? ... -No: def foo(a, b=FLAGS.my_thing): # sys.argv has not yet been parsed... +No: def foo(a, b=_FOO.value): # sys.argv has not yet been parsed... ... -No: def foo(a, b: Mapping = {}): # Could still get passed to unchecked code +No: def foo(a, b: Mapping = {}): # Could still get passed to unchecked code. ... ``` @@ -1036,7 +1074,7 @@ implement computations a subclass may ever want to override and extend. ### 2.14 True/False Evaluations -Use the "implicit" false if at all possible. +Use the "implicit" false if at all possible (with a few caveats). @@ -1168,8 +1206,8 @@ experienced Lisp and Scheme (and Haskell and ML and ...) programmers. #### 2.16.3 Cons -Can lead to confusing bugs. Such as this example based on -[PEP-0227](http://www.google.com/url?sa=D&q=http://www.python.org/dev/peps/pep-0227/): +Can lead to confusing bugs, such as this example based on +[PEP-0227](https://peps.python.org/pep-0227/): ```python i = 4 @@ -1271,13 +1309,13 @@ decorator runs (at import time, perhaps from `pydoc` or other tools). A decorator that is called with valid parameters should (as much as possible) be guaranteed to succeed in all cases. -Decorators are a special case of "top level code" - see [main](#s3.17-main) for +Decorators are a special case of "top-level code" - see [main](#s3.17-main) for more discussion. Never use `staticmethod` unless forced to in order to integrate with an API -defined in an existing library. Write a module level function instead. +defined in an existing library. Write a module-level function instead. -Use `classmethod` only when writing a named constructor or a class-specific +Use `classmethod` only when writing a named constructor, or a class-specific routine that modifies necessary global state such as a process-wide cache. @@ -1294,8 +1332,8 @@ or `__eq__` are implemented as Python methods) and their atomicity should not be relied upon. Neither should you rely on atomic variable assignment (since this in turn depends on dictionaries). -Use the Queue module's `Queue` data type as the preferred way to communicate -data between threads. Otherwise, use the threading module and its locking +Use the `queue` module's `Queue` data type as the preferred way to communicate +data between threads. Otherwise, use the `threading` module and its locking primitives. Prefer condition variables and `threading.Condition` instead of using lower-level locks. @@ -1410,14 +1448,6 @@ In code that may execute on versions as old as 3.5 rather than >= 3.7, import: from __future__ import generator_stop ``` -For legacy code with the burden of continuing to support 2.7, import: - -```python -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -``` - For more information read the [Python future statement definitions](https://docs.python.org/3/library/__future__.html) documentation. @@ -1428,19 +1458,7 @@ feature a specific future import enables in your code today, keeping it in place in the file prevents later modifications of the code from inadvertently depending on the older behavior. -Use other `from __future__` import statements as you see fit. We did not include -`unicode_literals` in our recommendations for 2.7 as it was not a clear win due -to implicit default codec conversion consequences it introduced in many places -within 2.7. Most dual-version 2-and-3 code was better off with explicit use of -`b''` and `u''` bytes and unicode string literals where necessary. - -##### The six, future, and past libraries - -When your project still needs to support use under both Python 2 and 3, use the -[six](https://pypi.org/project/six/), -[future](https://pypi.org/project/future/), and -[past](https://pypi.org/project/past/) libraries as you see fit. They exist to -make your code cleaner and life easier. +Use other `from __future__` import statements as you see fit. @@ -1450,13 +1468,12 @@ make your code cleaner and life easier. ### 2.21 Type Annotated Code -You can annotate Python 3 code with type hints according to -[PEP-484](https://www.python.org/dev/peps/pep-0484/), and type-check the code at -build time with a type checking tool like [pytype](https://github.com/google/pytype). - +You can annotate Python code with type hints according to +[PEP-484](https://peps.python.org/pep-0484/), and type-check the code at build +time with a type checking tool like [pytype](https://github.com/google/pytype). Type annotations can be in the source or in a -[stub pyi file](https://www.python.org/dev/peps/pep-0484/#stub-files). Whenever +[stub pyi file](https://peps.python.org/pep-0484/#stub-files). Whenever possible, annotations should be in the source. Use pyi files for third-party or extension modules. @@ -1471,22 +1488,16 @@ Type annotations (or "type hints") are for function or method arguments and return values: ```python -def func(a: int) -> List[int]: +def func(a: int) -> list[int]: ``` You can also declare the type of a variable using similar -[PEP-526](https://www.python.org/dev/peps/pep-0526/) syntax: +[PEP-526](https://peps.python.org/pep-0526/) syntax: ```python a: SomeType = some_func() ``` -Or by using a type comment in code that must support legacy Python versions. - -```python -a = some_func() # type: SomeType -``` - @@ -1552,23 +1563,53 @@ Explicit exceptions to the 80 character limit: - Long import statements. - URLs, pathnames, or long flags in comments. -- Long string module level constants not containing whitespace that would be +- Long string module-level constants not containing whitespace that would be inconvenient to split across lines such as URLs or pathnames. - Pylint disable comments. (e.g.: `# pylint: disable=invalid-name`) -Do not use backslash line continuation except for `with` statements requiring -three or more context managers. +Do not use a backslash for +[explicit line continuation](https://docs.python.org/3/reference/lexical_analysis.html#explicit-line-joining). -Make use of Python's +Instead, make use of Python's [implicit line joining inside parentheses, brackets and braces](http://docs.python.org/reference/lexical_analysis.html#implicit-line-joining). If necessary, you can add an extra pair of parentheses around an expression. +Note that this rule doesn't prohibit backslash-escaped newlines within strings +(see [below](#strings)). + ```python Yes: foo_bar(self, width, height, color='black', design=None, x='foo', emphasis=None, highlight=0) +``` - if (width == 0 and height == 0 and +```python + +Yes: if (width == 0 and height == 0 and color == 'red' and emphasis == 'strong'): + + (bridge_questions.clarification_on + .average_airspeed_of.unladen_swallow) = 'African or European?' + + with ( + very_long_first_expression_function() as spam, + very_long_second_expression_function() as beans, + third_thing() as eggs, + ): + place_order(eggs, beans, spam, beans) +``` + +```python + +No: if width == 0 and height == 0 and \ + color == 'red' and emphasis == 'strong': + + bridge_questions.clarification_on \ + .average_airspeed_of.unladen_swallow = 'African or European?' + + with very_long_first_expression_function() as spam, \ + very_long_second_expression_function() as beans, \ + third_thing() as eggs: + place_order(eggs, beans, spam, beans) ``` When a literal string won't fit on a single line, use parentheses for implicit @@ -1579,47 +1620,55 @@ x = ('This will build a very long long ' 'long long long long long long string') ``` -Within comments, put long URLs on their own line if necessary. +Prefer to break lines at the highest possible syntactic level. If you must break +a line twice, break it at the same syntactic level both times. ```python -Yes: # See details at - # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html +Yes: bridgekeeper.answer( + name="Arthur", quest=questlib.find(owner="Arthur", perilous=True)) + + answer = (a_long_line().of_chained_methods() + .that_eventually_provides().an_answer()) + + if ( + config is None + or 'editor.language' not in config + or config['editor.language'].use_spaces is False + ): + use_tabs() ``` ```python -No: # See details at - # http://www.example.com/us/developer/documentation/api/content/\ - # v2.0/csv_file_name_extension_full_specification.html -``` +No: bridgekeeper.answer(name="Arthur", quest=questlib.find( + owner="Arthur", perilous=True)) -It is permissible to use backslash continuation when defining a `with` statement -whose expressions span three or more lines. For two lines of expressions, use a -nested `with` statement: + answer = a_long_line().of_chained_methods().that_eventually_provides( + ).an_answer() + + if (config is None or 'editor.language' not in config or config[ + 'editor.language'].use_spaces is False): + use_tabs() -```python -Yes: with very_long_first_expression_function() as spam, \ - very_long_second_expression_function() as beans, \ - third_thing() as eggs: - place_order(eggs, beans, spam, beans) ``` +Within comments, put long URLs on their own line if necessary. + ```python -No: with VeryLongFirstExpressionFunction() as spam, \ - VeryLongSecondExpressionFunction() as beans: - PlaceOrder(beans, spam) +Yes: # See details at + # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html ``` ```python -Yes: with very_long_first_expression_function() as spam: - with very_long_second_expression_function() as beans: - place_order(beans, spam) +No: # See details at + # http://www.example.com/us/developer/documentation/api/content/\ + # v2.0/csv_file_name_extension_full_specification.html ``` Make note of the indentation of the elements in the line continuation examples above; see the [indentation](#s3.4-indentation) section for explanation. In all other cases where a line exceeds 80 characters, and the -[yapf](https://github.com/google/yapf/) +[Black](https://github.com/psf/black) or [Pyink](https://github.com/google/pyink) auto-formatter does not help bring the line below the limit, the line is allowed to exceed this maximum. Authors are encouraged to manually break the line up per the notes above when it is sensible. @@ -1669,27 +1718,27 @@ No: if (x): Indent your code blocks with *4 spaces*. -Never use tabs or mix tabs and spaces. In cases of implied line continuation, -you should align wrapped elements either vertically, as per the examples in the -[line length](#s3.2-line-length) section; or using a hanging indent of 4 spaces, -in which case there should be nothing after the open parenthesis or bracket on -the first line. +Never use tabs. Implied line continuation should align wrapped elements +vertically (see [line length examples](#s3.2-line-length)), or use a hanging +4-space indent. Closing (round, square or curly) brackets can be placed at the +end of the expression, or on separate lines, but then should be indented the +same as the line with the corresponding opening bracket. ```python -Yes: # Aligned with opening delimiter +Yes: # Aligned with opening delimiter. foo = long_function_name(var_one, var_two, var_three, var_four) meal = (spam, beans) - # Aligned with opening delimiter in a dictionary + # Aligned with opening delimiter in a dictionary. foo = { 'long_dictionary_key': value1 + value2, ... } - # 4-space hanging indent; nothing on first line + # 4-space hanging indent; nothing on first line. foo = long_function_name( var_one, var_two, var_three, var_four) @@ -1697,7 +1746,18 @@ Yes: # Aligned with opening delimiter spam, beans) - # 4-space hanging indent in a dictionary + # 4-space hanging indent; nothing on first line, + # closing parenthesis on a new line. + foo = long_function_name( + var_one, var_two, var_three, + var_four + ) + meal = ( + spam, + beans, + ) + + # 4-space hanging indent in a dictionary. foo = { 'long_dictionary_key': long_dictionary_value, @@ -1706,18 +1766,18 @@ Yes: # Aligned with opening delimiter ``` ```python -No: # Stuff on first line forbidden +No: # Stuff on first line forbidden. foo = long_function_name(var_one, var_two, var_three, var_four) meal = (spam, beans) - # 2-space hanging indent forbidden + # 2-space hanging indent forbidden. foo = long_function_name( var_one, var_two, var_three, var_four) - # No hanging indent in a dictionary + # No hanging indent in a dictionary. foo = { 'long_dictionary_key': long_dictionary_value, @@ -1739,13 +1799,15 @@ No: # Stuff on first line forbidden Trailing commas in sequences of items are recommended only when the closing container token `]`, `)`, or `}` does not appear on the same line as the final -element. The presence of a trailing comma is also used as a hint to our Python -code auto-formatter [YAPF](https://pypi.org/project/yapf/) to direct it to auto-format the container -of items to one item per line when the `,` after the final element is present. +element, as well as for tuples with a single element. The presence of a trailing +comma is also used as a hint to our Python code auto-formatter +[Black](https://github.com/psf/black) or [Pyink](https://github.com/google/pyink) +to direct it to auto-format the container of items to one item per line when the +`,` after the final element is present. ```python Yes: golomb3 = [0, 1, 3] -Yes: golomb4 = [ + golomb4 = [ 0, 1, 4, @@ -1758,8 +1820,7 @@ No: golomb4 = [ 0, 1, 4, - 6 - ] + 6,] ``` @@ -1769,9 +1830,9 @@ No: golomb4 = [ ### 3.5 Blank Lines Two blank lines between top-level definitions, be they function or class -definitions. One blank line between method definitions and between the `class` -line and the first method. No blank line following a `def` line. Use single -blank lines as you judge appropriate within functions or methods. +definitions. One blank line between method definitions and between the docstring +of a `class` and the first method. No blank line following a `def` line. Use +single blank lines as you judge appropriate within functions or methods. Blank lines need not be anchored to the definition. For example, related comments immediately preceding function, class, and method definitions can make @@ -1895,7 +1956,7 @@ No: Most `.py` files do not need to start with a `#!` line. Start the main file of a program with `#!/usr/bin/env python3` (to support virtualenvs) or `#!/usr/bin/python3` per -[PEP-394](https://www.python.org/dev/peps/pep-0394/). +[PEP-394](https://peps.python.org/pep-0394/). This line is used by the kernel to find the Python interpreter, but is ignored by Python when importing modules. It is only necessary on a file intended to be executed directly. @@ -1920,15 +1981,14 @@ Python uses *docstrings* to document code. A docstring is a string that is the first statement in a package, module, class or function. These strings can be extracted automatically through the `__doc__` member of the object and are used by `pydoc`. -(Try running `pydoc` on your module to see how it looks.) Always use the three -double-quote `"""` format for docstrings (per -[PEP 257](https://www.google.com/url?sa=D&q=http://www.python.org/dev/peps/pep-0257/)). -A docstring should be organized as a summary line (one physical line not -exceeding 80 characters) terminated by a period, question mark, or exclamation -point. When writing more (encouraged), this must be followed by a blank line, -followed by the rest of the docstring starting at the same cursor position as -the first quote of the first line. There are more formatting guidelines for -docstrings below. +(Try running `pydoc` on your module to see how it looks.) Always use the +three-double-quote `"""` format for docstrings (per +[PEP 257](https://peps.python.org/pep-0257/)). A docstring should be organized +as a summary line (one physical line not exceeding 80 characters) terminated by +a period, question mark, or exclamation point. When writing more (encouraged), +this must be followed by a blank line, followed by the rest of the docstring +starting at the same cursor position as the first quote of the first line. There +are more formatting guidelines for docstrings below. @@ -1937,19 +1997,19 @@ docstrings below. #### 3.8.2 Modules -Every file should contain license boilerplate. Choose the appropriate boilerplate for the license used by the project (for example, Apache 2.0, BSD, LGPL, GPL) +Every file should contain license boilerplate. Choose the appropriate boilerplate for the license used by the project (for example, Apache 2.0, BSD, LGPL, GPL). Files should start with a docstring describing the contents and usage of the module. ```python -"""A one line summary of the module or program, terminated by a period. +"""A one-line summary of the module or program, terminated by a period. Leave one blank line. The rest of this docstring should contain an overall description of the module or program. Optionally, it may also contain a brief description of exported classes and functions and/or usage examples. - Typical usage example: +Typical usage example: foo = ClassFoo() bar = foo.FunctionBar() @@ -1957,6 +2017,32 @@ examples. ``` + + + +##### 3.8.2.1 Test modules + +Module-level docstrings for test files are not required. They should be included +only when there is additional information that can be provided. + +Examples include some specifics on how the test should be run, an explanation of +an unusual setup pattern, dependency on the external environment, and so on. + +```python +"""This blaze test uses golden files. + +You can update those files by running +`blaze run //foo/bar:foo_test -- --update_golden_files` from the `google3` +directory. +""" +``` + +Docstrings that do not provide any new information should not be used. + +```python +"""Tests for foo.bar.""" +``` + @@ -1964,13 +2050,14 @@ examples. #### 3.8.3 Functions and Methods -In this section, "function" means a method, function, or generator. +In this section, "function" means a method, function, generator, or property. -A function must have a docstring, unless it meets all of the following criteria: +A docstring is mandatory for every function that has one or more of the +following properties: -- not externally visible -- very short -- obvious +- being part of the public API +- nontrivial size +- non-obvious logic A docstring should give enough information to write a call to the function without reading the function's code. The docstring should describe the @@ -1982,22 +2069,13 @@ details of a function's implementation that are not relevant to the caller are better expressed as comments alongside the code than within the function's docstring. -The docstring should be descriptive-style (`"""Fetches rows from a -Bigtable."""`) rather than imperative-style (`"""Fetch rows from a -Bigtable."""`). The docstring for a `@property` data descriptor should use the -same style as the docstring for an attribute or a +The docstring may be descriptive-style (`"""Fetches rows from a Bigtable."""`) +or imperative-style (`"""Fetch rows from a Bigtable."""`), but the style should +be consistent within a file. The docstring for a `@property` data descriptor +should use the same style as the docstring for an attribute or a function argument (`"""The Bigtable path."""`, rather than `"""Returns the Bigtable path."""`). -A method that overrides a method from a base class may have a simple docstring -sending the reader to its overridden method's docstring, such as `"""See base -class."""`. The rationale is that there is no need to repeat in many places -documentation that is already present in the base method's docstring. However, -if the overriding method's behavior is substantially different from the -overridden method, or details need to be provided (e.g., documenting additional -side effects), a docstring with at least those differences is required on the -overriding method. - Certain aspects of a function should be documented in special sections, listed below. Each section begins with a heading line, which ends with a colon. All sections other than the heading should maintain a hanging indent of two or four @@ -2018,18 +2096,21 @@ aptly described using a one-line docstring. [*Returns:* (or *Yields:* for generators)](#doc-function-returns) -: Describe the type and semantics of the return value. If the function only - returns None, this section is not required. It may also be omitted if the - docstring starts with Returns or Yields (e.g. `"""Returns row from Bigtable - as a tuple of strings."""`) and the opening sentence is sufficient to - describe the return value. Do not imitate 'NumPy style' - ([example](http://numpy.org/doc/stable/reference/generated/numpy.linalg.qr.html)), - which frequently documents a tuple return value as if it were multiple +: Describe the semantics of the return value, including any type information + that the type annotation does not provide. If the function only returns + None, this section is not required. It may also be omitted if the docstring + starts with "Return", "Returns", "Yield", or "Yields" (e.g. `"""Returns row + from Bigtable as a tuple of strings."""`) *and* the opening sentence is + sufficient to describe the return value. Do not imitate older 'NumPy style' + ([example](https://numpy.org/doc/1.24/reference/generated/numpy.linalg.qr.html)), + which frequently documented a tuple return value as if it were multiple return values with individual names (never mentioning the tuple). Instead, - describe such a return value as: "Returns a tuple (mat_a, mat_b), where + describe such a return value as: "Returns: A tuple (mat_a, mat_b), where mat_a is ..., and ...". The auxiliary names in the docstring need not necessarily correspond to any internal names used in the function body (as - those are not part of the API). + those are not part of the API). If the function uses `yield` (is a + generator), the `Yields:` section should document the object returned by + `next()`, instead of the generator object itself that the call evaluates to. [*Raises:*](#doc-function-raises) @@ -2041,10 +2122,11 @@ aptly described using a one-line docstring. part of the API). ```python -def fetch_smalltable_rows(table_handle: smalltable.Table, - keys: Sequence[Union[bytes, str]], - require_all_keys: bool = False, -) -> Mapping[bytes, Tuple[str, ...]]: +def fetch_smalltable_rows( + table_handle: smalltable.Table, + keys: Sequence[bytes | str], + require_all_keys: bool = False, +) -> Mapping[bytes, tuple[str, ...]]: """Fetches rows from a Smalltable. Retrieves rows pertaining to the given keys from the Table instance @@ -2078,10 +2160,11 @@ def fetch_smalltable_rows(table_handle: smalltable.Table, Similarly, this variation on `Args:` with a line break is also allowed: ```python -def fetch_smalltable_rows(table_handle: smalltable.Table, - keys: Sequence[Union[bytes, str]], - require_all_keys: bool = False, -) -> Mapping[bytes, Tuple[str, ...]]: +def fetch_smalltable_rows( + table_handle: smalltable.Table, + keys: Sequence[bytes | str], + require_all_keys: bool = False, +) -> Mapping[bytes, tuple[str, ...]]: """Fetches rows from a Smalltable. Retrieves rows pertaining to the given keys from the Table instance @@ -2114,6 +2197,47 @@ def fetch_smalltable_rows(table_handle: smalltable.Table, """ ``` + + + +##### 3.8.3.1 Overridden Methods + +A method that overrides a method from a base class does not need a docstring if +it is explicitly decorated with +[`@override`](https://typing-extensions.readthedocs.io/en/latest/#override) +(from `typing_extensions` or `typing` modules), unless the overriding method's +behavior materially refines the base method's contract, or details need to be +provided (e.g., documenting additional side effects), in which case a docstring +with at least those differences is required on the overriding method. + +```python +from typing_extensions import override + +class Parent: + def do_something(self): + """Parent method, includes docstring.""" + +# Child class, method annotated with override. +class Child(Parent): + @override + def do_something(self): + pass +``` + +```python +# Child class, but without @override decorator, a docstring is required. +class Child(Parent): + def do_something(self): + pass + +# Docstring is trivial, @override is sufficient to indicate that docs can be +# found in the base class. +class Child(Parent): + @override + def do_something(self): + """See base class.""" +``` + @@ -2122,16 +2246,16 @@ def fetch_smalltable_rows(table_handle: smalltable.Table, #### 3.8.4 Classes Classes should have a docstring below the class definition describing the class. -If your class has public attributes, they should be documented here in an -`Attributes` section and follow the same formatting as a +Public attributes, excluding [properties](#properties), should be documented +here in an `Attributes` section and follow the same formatting as a [function's `Args`](#doc-function-args) section. ```python class SampleClass: """Summary of class here. - Longer class information.... - Longer class information.... + Longer class information... + Longer class information... Attributes: likes_spam: A boolean indicating if we like SPAM or not. @@ -2139,12 +2263,47 @@ class SampleClass: """ def __init__(self, likes_spam: bool = False): - """Inits SampleClass with blah.""" + """Initializes the instance based on spam preference. + + Args: + likes_spam: Defines if instance exhibits this preference. + """ self.likes_spam = likes_spam self.eggs = 0 - def public_method(self): - """Performs operation blah.""" + @property + def butter_sticks(self) -> int: + """The number of butter sticks we have.""" +``` + +All class docstrings should start with a one-line summary that describes what +the class instance represents. This implies that subclasses of `Exception` +should also describe what the exception represents, and not the context in which +it might occur. The class docstring should not repeat unnecessary information, +such as that the class is a class. + +```python +# Yes: +class CheeseShopAddress: + """The address of a cheese shop. + + ... + """ + +class OutOfCheeseError(Exception): + """No more cheese is available.""" +``` + +```python +# No: +class CheeseShopAddress: + """Class that describes the address of a cheese shop. + + ... + """ + +class OutOfCheeseError(Exception): + """Raised when no more cheese is available.""" ``` @@ -2215,23 +2374,21 @@ punctuation, spelling, and grammar help with that goal. Use an [f-string](https://docs.python.org/3/reference/lexical_analysis.html#f-strings), the `%` operator, or the `format` method for formatting strings, even when the -parameters are all strings. Use your best judgment to decide between `+` and `%` -(or `format`) though. Do not use `%` or the `format` method for pure -concatenation. +parameters are all strings. Use your best judgment to decide between string +formatting options. A single join with `+` is okay but do not format with `+`. ```python -Yes: x = a + b +Yes: x = f'name: {name}; score: {n}' x = '%s, %s!' % (imperative, expletive) x = '{}, {}'.format(first, second) x = 'name: %s; score: %d' % (name, n) + x = 'name: %(name)s; score: %(score)d' % {'name':name, 'score':n} x = 'name: {}; score: {}'.format(name, n) - x = f'name: {name}; score: {n}' + x = a + b ``` ```python -No: x = '%s%s' % (a, b) # use + in this case - x = '{}{}'.format(a, b) # use + in this case - x = first + ', ' + second +No: x = first + ', ' + second x = 'name: ' + name + '; score: ' + str(n) ``` @@ -2242,7 +2399,7 @@ be optimized on CPython, that is an implementation detail. The conditions under which an optimization applies are not easy to predict and may change. Instead, add each substring to a list and `''.join` the list after the loop terminates, or write each substring to an `io.StringIO` buffer. These techniques -consistently have amortized-linear run time complexity. +consistently have amortized-linear run-time complexity. ```python Yes: items = [''] @@ -2321,6 +2478,11 @@ Don't do this. will collapse common leading spaces in each line.""") ``` +Note that using a backslash here does not violate the prohibition against +[explicit line continuation](#line-length); in this case, the backslash is +[escaping a newline](https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals) +in a string literal. + @@ -2386,7 +2548,7 @@ messages shown to the user) should follow three guidelines: ```python Yes: if not 0 <= p <= 1: - raise ValueError(f'Not a probability: {p!r}') + raise ValueError(f'Not a probability: {p=}') try: os.rmdir(workdir) @@ -2398,7 +2560,7 @@ messages shown to the user) should follow three guidelines: ```python No: if p < 0 or p > 1: # PROBLEM: also false for float('nan')! - raise ValueError(f'Not a probability: {p!r}') + raise ValueError(f'Not a probability: {p=}') try: os.rmdir(workdir) @@ -2497,25 +2659,36 @@ documentation must explain clearly how resource lifetime is managed. Use `TODO` comments for code that is temporary, a short-term solution, or good-enough but not perfect. -A `TODO` comment begins with the string `TODO` in all caps and a parenthesized -name, e-mail address, or other identifier -of the person or issue with the best context about the problem. This is followed -by an explanation of what there is to do. - +A `TODO` comment begins with the word `TODO` in all caps, a following colon, and +a link to a resource that contains the context, ideally a bug reference. A bug +reference is preferable because bugs are tracked and have follow-up comments. +Follow this piece of context with an explanatory string introduced with a hyphen +`-`. The purpose is to have a consistent `TODO` format that can be searched to find -out how to get more details. A `TODO` is not a commitment that the person -referenced will fix the problem. Thus when you create a -`TODO`, it is almost always your name -that is given. +out how to get more details. ```python -# TODO(kl@gmail.com): Use a "*" here for string repetition. -# TODO(Zeke) Change this to use relations. +# TODO: crbug.com/192795 - Investigate cpufreq optimizations. +``` + +Old style, formerly recommended, but discouraged for use in new code: + + +```python +# TODO(crbug.com/192795): Investigate cpufreq optimizations. +# TODO(yourusername): Use a "\*" here for concatenation operator. +``` + +Avoid adding TODOs that refer to an individual or team as the context: + +```python +# TODO: @yourusername - File an issue and use a '*' for repetition. ``` If your `TODO` is of the form "At a future date do something" make sure that you either include a very specific date ("Fix by November 2009") or a very specific -event ("Remove this code when all clients can handle XML responses."). +event ("Remove this code when all clients can handle XML responses.") that +future code maintainers will comprehend. Issues are ideal for tracking this. @@ -2524,14 +2697,15 @@ event ("Remove this code when all clients can handle XML responses."). ### 3.13 Imports formatting Imports should be on separate lines; there are -[exceptions for `typing` imports](#typing-imports). +[exceptions for `typing` and `collections.abc` imports](#typing-imports). E.g.: ```python -Yes: import os +Yes: from collections.abc import Mapping, Sequence + import os import sys - from typing import Mapping, Sequence + from typing import Any, NewType ``` ```python @@ -2546,9 +2720,7 @@ grouped from most generic to least generic: 1. Python future import statements. For example: ```python - from __future__ import absolute_import - from __future__ import division - from __future__ import print_function + from __future__ import annotations ``` See [above](#from-future-imports) for more information about those. @@ -2576,7 +2748,7 @@ grouped from most generic to least generic: ``` 5. **Deprecated:** application-specific imports that are part of the same - top level + top-level sub-package as this file. For example: @@ -2692,10 +2864,11 @@ change in complexity. `module_name`, `package_name`, `ClassName`, `method_name`, `ExceptionName`, `function_name`, `GLOBAL_CONSTANT_NAME`, `global_var_name`, `instance_var_name`, -`function_parameter_name`, `local_var_name`. +`function_parameter_name`, `local_var_name`, `query_proper_noun_for_thing`, +`send_acronym_via_https`. -Function names, variable names, and filenames should be descriptive; eschew +Function names, variable names, and filenames should be descriptive; avoid abbreviation. In particular, do not use abbreviations that are ambiguous or unfamiliar to readers outside your project, and do not abbreviate by deleting letters within a word. @@ -2713,6 +2886,8 @@ Always use a `.py` filename extension. Never use dashes. - counters or iterators (e.g. `i`, `j`, `k`, `v`, et al.) - `e` as an exception identifier in `try/except` statements. - `f` as a file handle in `with` statements + - private [type variables](#typing-type-var) with no constraints (e.g. + `_T = TypeVar("_T")`, `_P = ParamSpec("_P")`) Please be mindful not to abuse single-character naming. Generally speaking, descriptiveness should be proportional to the name's scope of visibility. @@ -2738,7 +2913,9 @@ Always use a `.py` filename extension. Never use dashes. class. - Prepending a single underscore (`_`) has some support for protecting module - variables and functions (linters will flag protected member access). + variables and functions (linters will flag protected member access). Note + that it is okay for unit tests to access protected constants from the + modules under test. - Prepending a double underscore (`__` aka "dunder") to an instance variable or method effectively makes the variable or method private to its class @@ -2755,11 +2932,11 @@ Always use a `.py` filename extension. Never use dashes. a class. ("wait -- did I write `import StringIO` or `from StringIO import StringIO`?") -- Underscores may appear in *unittest* method names starting with `test` to - separate logical components of the name, even if those components use - CapWords. One possible pattern is `test_`; for - example `testPop_EmptyStack` is okay. There is no One Correct Way to name - test methods. +- New *unit test* files follow PEP 8 compliant lower\_with\_under method + names, for example, `test__`. For consistency(\*) + with legacy modules that follow CapWords function names, underscores may + appear in method names starting with `test` to separate logical components + of the name. One possible pattern is `test_`. @@ -2944,13 +3121,31 @@ the function into smaller and more manageable pieces. #### 3.19.1 General Rules -* Familiarize yourself with - [PEP-484](https://www.python.org/dev/peps/pep-0484/). -* In methods, only annotate `self`, or `cls` if it is necessary for proper - type information. e.g., `@classmethod def create(cls: Type[T]) -> T: return - cls()` +* Familiarize yourself with [PEP-484](https://peps.python.org/pep-0484/). + +* Annotating `self` or `cls` is generally not necessary. + [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) can be + used if it is necessary for proper type information, e.g. + + ```python + from typing import Self + + class BaseClass: + @classmethod + def create(cls) -> Self: + ... + + def difference(self, other: Self) -> float: + ... + ``` + +* Similarly, don't feel compelled to annotate the return value of `__init__` + (where `None` is the only valid option). + * If any other variable or a returned type should not be expressed, use `Any`. + * You are not required to annotate all the functions in a module. + - At least annotate your public APIs. - Use judgment to get to a good balance between safety and clarity on the one hand, and flexibility on the other. @@ -2970,12 +3165,16 @@ the function into smaller and more manageable pieces. Try to follow the existing [indentation](#indentation) rules. After annotating, many function signatures will become "one parameter per line". +To ensure the return type is also given its own line, a comma can be placed +after the last parameter. ```python -def my_method(self, - first_var: int, - second_var: Foo, - third_var: Optional[Bar]) -> int: +def my_method( + self, + first_var: int, + second_var: Foo, + third_var: Bar | None, +) -> int: ... ``` @@ -2989,23 +3188,27 @@ def my_method(self, first_var: int) -> int: ``` If the combination of the function name, the last parameter, and the return type -is too long, indent by 4 in a new line. +is too long, indent by 4 in a new line. When using line breaks, prefer putting +each parameter and the return type on their own lines and aligning the closing +parenthesis with the `def`: ```python +Yes: def my_method( - self, first_var: int) -> Tuple[MyLongType1, MyLongType1]: + self, + other_arg: MyLongType | None, +) -> tuple[MyLongType1, MyLongType1]: ... ``` -When the return type does not fit on the same line as the last parameter, the -preferred way is to indent the parameters by 4 on a new line and align the -closing parenthesis with the `def`. +Optionally, the return type may be put on the same line as the last parameter: ```python -Yes: +Okay: def my_method( - self, other_arg: Optional[MyLongType] -) -> Dict[OtherLongType, MyLongType]: + self, + first_var: int, + second_var: int) -> dict[OtherLongType, MyLongType]: ... ``` @@ -3016,8 +3219,8 @@ opening one, but this is less readable. ```python No: def my_method(self, - other_arg: Optional[MyLongType] - ) -> Dict[OtherLongType, MyLongType]: + other_arg: MyLongType | None, + ) -> dict[OtherLongType, MyLongType]: ... ``` @@ -3027,10 +3230,11 @@ too long to be on a single line (try to keep sub-types unbroken). ```python def my_method( self, - first_var: Tuple[List[MyLongType1], - List[MyLongType2]], - second_var: List[Dict[ - MyLongType3, MyLongType4]]) -> None: + first_var: tuple[list[MyLongType1], + list[MyLongType2]], + second_var: list[dict[ + MyLongType3, MyLongType4]], +) -> None: ... ``` @@ -3062,17 +3266,29 @@ def my_function( #### 3.19.3 Forward Declarations -If you need to use a class name from the same module that is not yet defined -- -for example, if you need the class inside the class declaration, or if you use a -class that is defined below -- either use `from __future__ import annotations` -for simple cases or use a string for the class name. +If you need to use a class name (from the same module) that is not yet +defined -- for example, if you need the class name inside the declaration of +that class, or if you use a class that is defined later in the code -- either +use `from __future__ import annotations` or use a string for the class name. ```python +Yes: from __future__ import annotations class MyClass: + def __init__(self, stack: Sequence[MyClass], item: OtherClass) -> None: + +class OtherClass: + ... +``` + +```python +Yes: +class MyClass: + def __init__(self, stack: Sequence['MyClass'], item: 'OtherClass') -> None: - def __init__(self, stack: Sequence[MyClass]) -> None: +class OtherClass: + ... ``` @@ -3081,8 +3297,7 @@ class MyClass: #### 3.19.4 Default Values -As per -[PEP-008](https://www.python.org/dev/peps/pep-0008/#other-recommendations), use +As per [PEP-008](https://peps.python.org/pep-0008/#other-recommendations), use spaces around the `=` *only* for arguments that have both a type annotation and a default value. @@ -3107,18 +3322,18 @@ def func(a:int=0) -> int: In the Python type system, `NoneType` is a "first class" type, and for typing purposes, `None` is an alias for `NoneType`. If an argument can be `None`, it -has to be declared! You can use `Union`, but if there is only one other type, -use `Optional`. +has to be declared! You can use `|` union type expressions (recommended in new +Python 3.10+ code), or the older `Optional` and `Union` syntaxes. -Use explicit `Optional` instead of implicit `Optional`. Earlier versions of PEP -484 allowed `a: str = None` to be interpreted as `a: Optional[str] = None`, but -that is no longer the preferred behavior. +Use explicit `X | None` instead of implicit. Earlier versions of PEP 484 allowed +`a: str = None` to be interpreted as `a: str | None = None`, but that is no +longer the preferred behavior. ```python Yes: -def func(a: Optional[str], b: Optional[str] = None) -> str: +def modern_or_union(a: str | int | None, b: str | None = None) -> str: ... -def multiple_nullable_union(a: Union[None, str, int]) -> str: +def union_optional(a: Union[str, int, None], b: Optional[str] = None) -> str: ... ``` @@ -3141,16 +3356,14 @@ def implicit_optional(a: str = None) -> str: You can declare aliases of complex types. The name of an alias should be CapWorded. If the alias is used only in this module, it should be \_Private. -For example, if the name of the module together with the name of the type is too -long: +Note that the `: TypeAlias` annotation is only supported in versions 3.10+. ```python -_ShortName = module_with_long_name.TypeWithLongName -ComplexMap = Mapping[str, List[Tuple[int, int]]] -``` +from typing import TypeAlias -Other examples are complex nested types and multiple return variables from a -function (as a tuple). +_LossAndGradient: TypeAlias = tuple[tf.Tensor, tf.Tensor] +ComplexTFMap: TypeAlias = Mapping[str, _LossAndGradient] +``` @@ -3175,25 +3388,26 @@ ignore`. #### 3.19.8 Typing Variables -If an internal variable has a type that is hard or impossible to infer, you can -specify its type in a couple ways. - - -[*Type Comments:*](#type-comments) -: Use a `# type:` comment on the end of the line - -```python -a = SomeUndecoratedFunction() # type: Foo -``` - [*Annotated Assignments*](#annotated-assignments) -: Use a colon and type between the variable name and value, as with function - arguments. +: If an internal variable has a type that is hard or impossible to infer, + specify its type with an annotated assignment - use a colon and type between + the variable name and value (the same as is done with function arguments + that have a default value): -```python -a: Foo = SomeUndecoratedFunction() -``` + ```python + a: Foo = SomeUndecoratedFunction() + ``` + + +[*Type Comments*](#type-comments) +: Though you may see them remaining in the codebase (they were necessary + before Python 3.6), do not add any more uses of a `# type: ` + comment on the end of the line: + + ```python + a = SomeUndecoratedFunction() # type: Foo + ``` @@ -3207,9 +3421,9 @@ have a single repeated type or a set number of elements with different types. The latter is commonly used as the return type from a function. ```python -a = [1, 2, 3] # type: List[int] -b = (1, 2, 3) # type: Tuple[int, ...] -c = (1, "2", 3.5) # type: Tuple[int, str, float] +a: list[int] = [1, 2, 3] +b: tuple[int, ...] = (1, 2, 3) +c: tuple[int, str, float] = (1, "2", 3.5) ``` @@ -3218,23 +3432,31 @@ c = (1, "2", 3.5) # type: Tuple[int, str, float] -#### 3.19.10 TypeVars +#### 3.19.10 Type variables The Python type system has -[generics](https://www.python.org/dev/peps/pep-0484/#generics). The factory -function `TypeVar` is a common way to use them. +[generics](https://peps.python.org/pep-0484/#generics). A type variable, such as +`TypeVar` and `ParamSpec`, is a common way to use them. Example: ```python -from typing import List, TypeVar -T = TypeVar("T") +from collections.abc import Callable +from typing import ParamSpec, TypeVar +_P = ParamSpec("_P") +_T = TypeVar("_T") ... -def next(l: List[T]) -> T: +def next(l: list[_T]) -> _T: return l.pop() + +def print_when_called(f: Callable[_P, _T]) -> Callable[_P, _T]: + def inner(*args: _P.args, **kwargs: _P.kwargs) -> _T: + print("Function was called") + return f(*args, **kwargs) + return inner ``` -A TypeVar can be constrained: +A `TypeVar` can be constrained: ```python AddableType = TypeVar("AddableType", int, float, str) @@ -3243,8 +3465,7 @@ def add(a: AddableType, b: AddableType) -> AddableType: ``` A common predefined type variable in the `typing` module is `AnyStr`. Use it for -multiple annotations that can be `bytes` or `unicode` and must all be the same -type. +multiple annotations that can be `bytes` or `str` and must all be the same type. ```python from typing import AnyStr @@ -3254,52 +3475,44 @@ def check_length(x: AnyStr) -> AnyStr: raise ValueError() ``` - - - - - -#### 3.19.11 String types +A type variable must have a descriptive name, unless it meets all of the +following criteria: -The proper type for annotating strings depends on what versions of Python the -code is intended for. +* not externally visible +* not constrained -Prefer to use `str`, though `Text` is also acceptable. Be consistent in using -one or the other. For code that deals with binary data, use `bytes`. For Python -2 compatible code that processes text data (`str` or `unicode` in Python 2, -`str` in Python 3), use `Text`. +```python +Yes: + _T = TypeVar("_T") + _P = ParamSpec("_P") + AddableType = TypeVar("AddableType", int, float, str) + AnyFunction = TypeVar("AnyFunction", bound=Callable) +``` ```python -def deals_with_text_data_in_py3(x: str) -> str: - ... -def deals_with_binary_data(x: bytes) -> bytes: - ... -def py2_compatible_text_data_processor(x: Text) -> Text: - ... +No: + T = TypeVar("T") + P = ParamSpec("P") + _T = TypeVar("_T", int, float, str) + _F = TypeVar("_F", bound=Callable) ``` -In some uncommon Python 2 compatibility cases, `str` may make sense instead of -`Text`, typically to aid compatibility when the return types aren't the same -between Python 2 and Python 3. Never use `unicode` as it doesn't exist in Python -3. The reason this discrepancy exists is because `str` means something different -in Python 2 than in Python 3. + + + -No: + +#### 3.19.11 String types -```python -def py2_code(x: str) -> unicode: - ... -``` +> Do not use `typing.Text` in new code. It's only for Python 2/3 compatibility. -If the type can be either bytes or text, use `Union`, with the appropriate text -type. +Use `str` for string/text data. For code that deals with binary data, use +`bytes`. ```python -from typing import Text, Union -... -def py3_only(x: Union[bytes, str]) -> Union[bytes, str]: +def deals_with_text_data(x: str) -> str: ... -def py2_compatible(x: Union[bytes, Text]) -> Union[bytes, Text]: +def deals_with_binary_data(x: bytes) -> bytes: ... ``` @@ -3314,24 +3527,36 @@ return type is the same as the argument type in the code above, use #### 3.19.12 Imports For Typing -For classes from the `typing` module, always import the class itself. You are -explicitly allowed to import multiple specific classes on one line from the -`typing` module. Ex: +For symbols (including types, functions, and constants) from the `typing` or +`collections.abc` modules used to support static analysis and type checking, +always import the symbol itself. This keeps common annotations more concise and +matches typing practices used around the world. You are explicitly allowed to +import multiple specific symbols on one line from the `typing` and +`collections.abc` modules. For example: ```python -from typing import Any, Dict, Optional +from collections.abc import Mapping, Sequence +from typing import Any, Generic, cast, TYPE_CHECKING ``` -Given that this way of importing from `typing` adds items to the local -namespace, any names in `typing` should be treated similarly to keywords, and -not be defined in your Python code, typed or not. If there is a collision -between a type and an existing name in a module, import it using `import x as -y`. +Given that this way of importing adds items to the local namespace, names in +`typing` or `collections.abc` should be treated similarly to keywords, and not +be defined in your Python code, typed or not. If there is a collision between a +type and an existing name in a module, import it using `import x as y`. ```python from typing import Any as AnyType ``` +Prefer to use built-in types as annotations where available. Python supports +type annotations using parametric container types via +[PEP-585](https://peps.python.org/pep-0585/), introduced in Python 3.9. + +```python +def generate_foo_scores(foo: set[str]) -> list[float]: + ... +``` + @@ -3340,7 +3565,7 @@ from typing import Any as AnyType Use conditional imports only in exceptional cases where the additional imports needed for type checking must be avoided at runtime. This pattern is -discouraged; alternatives such as refactoring the code to allow top level +discouraged; alternatives such as refactoring the code to allow top-level imports should be preferred. Imports that are needed only for type annotations can be placed within an `if @@ -3376,8 +3601,8 @@ because each module has to depend on the other. Replace modules that create circular dependency imports with `Any`. Set an [alias](#typing-aliases) with a meaningful name, and use the real type name from -this module (any attribute of Any is Any). Alias definitions should be separated -from the last import by one line. +this module (any attribute of `Any` is `Any`). Alias definitions should be +separated from the last import by one line. ```python from typing import Any @@ -3397,19 +3622,18 @@ def my_method(self, var: "some_mod.SomeType") -> None: #### 3.19.15 Generics When annotating, prefer to specify type parameters for generic types; otherwise, -[the generics' parameters will be assumed to be `Any`](https://www.python.org/dev/peps/pep-0484/#the-any-type). +[the generics' parameters will be assumed to be `Any`](https://peps.python.org/pep-0484/#the-any-type). ```python -def get_names(employee_ids: List[int]) -> Dict[int, Any]: +# Yes: +def get_names(employee_ids: Sequence[int]) -> Mapping[int, str]: ... ``` ```python -# These are both interpreted as get_names(employee_ids: List[Any]) -> Dict[Any, Any] -def get_names(employee_ids: list) -> Dict: - ... - -def get_names(employee_ids: List) -> Dict: +# No: +# This is interpreted as get_names(employee_ids: Sequence[Any]) -> Mapping[Any, Any] +def get_names(employee_ids: Sequence) -> Mapping: ... ``` @@ -3418,13 +3642,15 @@ remember that in many cases [`TypeVar`](#typing-type-var) might be more appropriate: ```python -def get_names(employee_ids: List[Any]) -> Dict[Any, str]: +# No: +def get_names(employee_ids: Sequence[Any]) -> Mapping[Any, str]: """Returns a mapping from employee ID to employee name for given IDs.""" ``` ```python -T = TypeVar('T') -def get_names(employee_ids: List[T]) -> Dict[T, str]: +# Yes: +_T = TypeVar('_T') +def get_names(employee_ids: Sequence[_T]) -> Mapping[_T, str]: """Returns a mapping from employee ID to employee name for given IDs.""" ``` @@ -3437,14 +3663,20 @@ def get_names(employee_ids: List[T]) -> Dict[T, str]: *BE CONSISTENT*. If you're editing code, take a few minutes to look at the code around you and -determine its style. If they use spaces around all their arithmetic operators, -you should too. If their comments have little boxes of hash marks around them, -make your comments have little boxes of hash marks around them too. +determine its style. If they use `_idx` suffixes in index variable names, you +should too. If their comments have little boxes of hash marks around them, make +your comments have little boxes of hash marks around them too. The point of having style guidelines is to have a common vocabulary of coding so people can concentrate on what you're saying rather than on how you're saying it. We present global style rules here so people know the vocabulary, but local style is also important. If code you add to a file looks drastically different from the existing code around it, it throws readers out of their rhythm when -they go to read it. Avoid this. +they go to read it. + +However, there are limits to consistency. It applies more heavily locally and on +choices unspecified by the global style. Consistency should not generally be +used as a justification to do things in an old style without considering the +benefits of the new style, or the tendency of the codebase to converge on newer +styles over time. diff --git a/script/build.py b/script/build.py index 495402d..2632db2 100644 --- a/script/build.py +++ b/script/build.py @@ -8,8 +8,8 @@ import os import re -find_link = re.compile('\[(\w+)\]\(([\w\\\/\_\.\:]+)\)') -find_nums = re.compile('([0-9]+)\.([0-9]*).*') +find_link = re.compile('\\[(\\w+)\\]\\(([\\w\\\\/_.:]+)\\)') +find_nums = re.compile('([0-9]+)\\.([0-9]*).*') readme = [] tree = []