PEP 379 – 대입 표현식 추가
- Author:
- Jervis Whitley <jervisau at gmail.com>
- Status:
- Withdrawn
- Type:
- Standards Track
- Created:
- 14-Mar-2009
- Python-Version:
- 2.7, 3.2
- Post-History:
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 거의 모든 위치에서 표현식의 결과를 대입할 수 있도록 Python 언어에 새로운 대입 표현식을 추가합니다. 새 표현식을 사용하면 표현식의 결과를 처음 사용하는 곳(예를 들어 비교식 안)에서 대입할 수 있습니다.
동기와 요약
Issue1714448 “if something as x:” [1]은 if 문에서 표현식의 결과를 이름에 대입할 수 있게 하는 기능을 설명합니다. 이 기능에서는 as 문법을 이 목적에 빌려 쓸 수 있다고 가정했습니다. 관심 대상이 표현식 자체가 아니라 표현식을 구성하는 항 중 하나인 경우가 많습니다. 분명히 말하자면, 다음과 같은 것은:
if (f_result() == [1, 2, 3]) as res:
매우 제한적으로 보이는데, 다음과 같은 것이:
if (f_result() as res) == [1, 2, 3]:
아마도 원하는 결과일 것입니다.
사용 사례
끝부분의 예제 절을 참고하십시오.
명세
다음과 같은 (명목상의) 문법을 갖는 새로운 표현식을 제안합니다:
EXPR -> VAR
이 단일 표현식은 다음을 수행합니다:
- 임의의 표현식인
EXPR의 값을 평가합니다. - 그 결과를 단일 대입 대상인
VAR에 대입합니다. EXPR의 결과를 스택 최상단(Top of Stack, TOS)에 남겨 둡니다.
여기서는 EXPR의 결과가 VAR에 대입된다는 개념을 나타내기 위해 -> (또는 RARROW)를 사용했습니다.
제안된 문법은 다음과 같이 변환됩니다:
VAR = (EXPR)
(EXPR)
대입 대상은 속성, 서브스크립트, 이름 중 하나일 수 있습니다:
f() -> name[0] # where 'name' exists previously.
f() -> name.attr # again 'name' exists prior to this expression.
f() -> name
이 표현식은 현재 표현식이 허용되는 모든 곳에서 사용할 수 있어야 합니다.
현재 잘못된 대입 과정에서 발생하는 모든 예외는 대입 표현식을 사용할 때도 계속 발생합니다. 예를 들어 name이 이전에 정의되지 않았다면 위의 예제 1과 2에서 NameError가 발생하고, 인덱스 0이 범위를 벗어났다면 IndexError가 발생합니다.
표준 라이브러리의 예제
다음 두 예제는 표준 라이브러리를 간단히 검색한 뒤 고른 것으로, 둘 다 검색 당시 마침 열려 있던 ast.py에서 가져왔습니다.
원본:
def walk(node):
from collections import deque
todo = deque([node])
while todo:
node = todo.popleft()
todo.extend(iter_child_nodes(node))
yield node
대입 표현식 사용:
def walk(node):
from collections import deque
todo = deque([node])
while todo:
todo.extend(iter_child_nodes(todo.popleft() -> node))
yield node
원본:
def get_docstring(node, clean=True):
if not isinstance(node, (FunctionDef, ClassDef, Module)):
raise TypeError("%r can't have docstrings"
% node.__class__.__name__)
if node.body and isinstance(node.body[0], Expr) and \
isinstance(node.body[0].value, Str):
if clean:
import inspect
return inspect.cleandoc(node.body[0].value.s)
return node.body[0].value.s
대입 표현식 사용:
def get_docstring(node, clean=True):
if not isinstance(node, (FunctionDef, ClassDef, Module)):
raise TypeError("%r can't have docstrings"
% node.__class__.__name__)
if node.body -> body and isinstance(body[0] -> elem, Expr) and \
isinstance(elem.value -> value, Str):
if clean:
import inspect
return inspect.cleandoc(value.s)
return value.s
예시
아래 예제들은 대입 표현식의 바람직한 특징 몇 가지와 발생할 수 있는 코너 케이스 몇 가지를 보여 줍니다.
- 나중에 사용하기 위한 if 문에서의 대입:
def expensive(): import time; time.sleep(1) return 'spam' if expensive() -> res in ('spam', 'eggs'): dosomething(res)
- while 루프 절에서의 대입:
while len(expensive() -> res) == 4: dosomething(res)
- for 루프의 이터레이터 객체 유지하기:
for ch in expensive() -> res: sell_on_internet(res)
- 코너 케이스:
for ch -> please_dont in expensive(): pass # who would want to do this? Not I.
참고 문헌
Copyright
This document has been placed in the public domain.