[Rejected] PEP 637 - Support for indexing with keyword arguments
원문 링크: PEP 637 - Support for indexing with keyword arguments
상태: Rejected 유형: Standards Track 작성일: 24-Aug-2020
PEP 637: 키워드 인자를 사용한 인덱싱 지원 (결론: 거부됨)
요약
PEP 637은 Python의 아이템 접근(item access), 즉 []
(대괄호)를 사용한 인덱싱 연산에 키워드 인자(keyword arguments)를 허용하도록 확장하는 것을 제안했습니다. 이 제안은 f(a=1, b=2)
와 같은 함수 호출에서 키워드 인자를 사용하는 것과 유사하게 x[a=1, b=2]
와 같은 형태로 인덱싱을 가능하게 하는 것을 목표로 했습니다. 이 PEP는 이전 PEP 472의 후속작으로, 데이터 분석 라이브러리(Pandas, Xarray)의 사용 증가와 타입 힌트(Type Hint)의 발전으로 인한 새로운 요구 사항을 반영했습니다. 하지만 PEP 637은 최종적으로 거부되었습니다. 새로운 문법을 도입하는 비용이 예상되는 이점을 상회하지 않는다는 것이 주요 거부 사유였습니다.
1. 개요 (Abstract)
현재 키워드 인자는 함수 호출에서는 허용되지만, 아이템 접근(인덱싱)에서는 허용되지 않습니다. 이 PEP는 Python을 확장하여 아이템 접근에도 키워드 인자를 허용할 것을 제안했습니다.
예를 들어, 일반적인 함수 호출에서 키워드 인자는 다음과 같이 사용됩니다:
val = f(1, 2, a=3, b=4)
이 제안은 인덱싱 연산에도 유사한 구문을 허용하도록 확장하는 것입니다:
val = x[1, 2, a=3, b=4] # getitem
x[1, 2, a=3, b=4] = val # setitem
del x[1, 2, a=3, b=4] # delitem
또한, 인자의 단일(*
) 및 이중(**
) 스타 언패킹(unpacking)도 지원할 예정이었습니다:
val = x[*(1, 2), **{'a': 3, 'b': 4}] # 위와 동일
이 PEP는 2019년에 관심 부족으로 거부되었던 PEP 472의 후속작으로, 이후 해당 기능에 대한 관심이 다시 증가했습니다.
2. 배경 (Overview - Background)
PEP 472는 2014년에 처음 제안되었으나, 5년간의 논의에도 불구하고 기능에 대한 관심 부족으로 2019년에 거부되었습니다.
그러나 PEP 484에서 타입 힌트가 도입되면서 Sequence[int]
와 같이 대괄호([]
) 표기법이 타입 어노테이션(annotation)을 풍부하게 하는 데 일관되게 사용되었습니다. 또한, Pandas나 Xarray와 같은 데이터 분석 패키지의 사용이 크게 늘어났습니다. 이들 패키지는 테이블의 컬럼(Pandas)이나 다차원 배열의 축(Xarray)을 이름으로 설명하며 특정 데이터를 이름으로 접근할 수 있지만, 현재는 인덱스 표기법([]
)을 이 기능에 사용할 수 없습니다.
이러한 배경으로 인해 이름이 있는 정보를 허용하는 보다 유연한 문법에 대한 관심이 Python-Ideas 메일링 리스트에서 다시 제기되었고, 이에 따라 구현 전략에 대한 일반적인 합의가 이루어졌습니다.
3. 사용 사례 (Use cases)
키워드 인자를 통한 인덱싱이 유용할 수 있는 몇 가지 실제 사용 사례는 다음과 같습니다:
- 인덱스의 의미 명확화: 인덱스 순서의 우발적인 반전을 방지하고, 인덱스에 더 명확한 의미를 부여합니다.
grid_position[x=3, y=5, z=8] rain_amount[time=0:12, location=location] matrix[row=20, col=40]
- 제네릭(Generics) 사용 시 타입 어노테이션 강화:
def function(value: MyType[T=int]):
- 도메인 특정 언어(Domain Specific Language, DSL) 표기법: 계산 물리학 및 화학과 같은 분야에서
Basis[Z=5]
와 같은 표기법은 정확도 수준을 나타내는 DSL 표기법으로 사용될 수 있습니다.low_accuracy_energy = computeEnergy(molecule, BasisSet[Z=3])
- Pandas 및 Xarray에서 이름 기반 접근:
- Pandas의 경우
df[df['x'] == 1]
대신df[x=1]
로 대체 가능. - Xarray의
data.isel(row=10)
대신data[row=10]
로 대체 가능. - 더 복잡한 슬라이싱 예시:
# 기존 문법 da.isel(space=0, time=slice(None, 2))[...] = spam # 새로운 문법 da[space=0, time=:2] = spam
- Pandas의 경우
- 키워드 인자를
__getitem__
으로 전달:trio.run
과 같이 다른 함수를 인자로 받는 함수에서, 타겟 함수로 전달될 인자와 런타임 설정을 위한 인자를 구분하는 데 유용합니다.# 기존: functools.partial 또는 .option() 메서드 사용 trio.run(functools.partial(func, param2=value2), value1, name="func") # 제안된 문법 trio.run[name="func"](func, value1, param2=value2)
- PEP 646 Variadic Generics 지원:
a[*x]
와 같은 가변 제네릭에서 스타 인자(star arguments)의 가용성을 높입니다.
이러한 표기법이 어떻게 해석될지는 구현에 달려 있으며, 이 PEP는 전달된 키워드 인자에 대한 Python의 동작 방식만 정의하며, 이러한 인자들이 구현 클래스에 의해 어떻게 해석되고 사용되어야 하는지는 정의하지 않습니다.
4. 인덱싱 연산의 현재 상태 (Current status of indexing operation)
obj[x]
와 같은 서브스크립트(subscripting) 연산은 사실상 obj(x)
와 비교하여 여러 차이점과 제약 사항이 있는 특수화된 형태의 함수 호출 구문입니다. 현재 Python 구문은 인덱스를 표현하기 위해 위치(position)에만 초점을 맞추며, 슬라이스(slice)와 같은 비점별(non-punctiform) 선택을 위한 문법적 설탕(syntactic sugar)을 포함합니다.
일반적인 예시:
a[3] # 'a'의 네 번째 요소 반환
a[1:10:2] # 슬라이스 표기법
a[3, 2] # 다차원 배열을 위한 다중 인덱스
이는 __getitem__
, __setitem__
, __delitem__
이라는 특수 메서드(dunder call) 호출로 변환됩니다.
함수 호출과 비교했을 때 인덱싱 호출의 근본적인 차이점은 다음과 같습니다:
- 의미 차이: 함수 호출은 “임의의 함수 호출”을 의미하지만, 인덱싱은 일반적으로 “찾아보기(lookup)”를 의미하며 엔티티의 부분 집합이나 특정 측면을 가리킵니다.
- 할당 가능성: 인덱싱은 값을 가져오고(getting) 설정하는(setting) 두 가지 모두에 사용될 수 있지만, 함수는 할당문의 왼쪽에 올 수 없습니다.
x = a[1, 2] # 유효 a[1, 2] = 5 # 유효 x = f(1, 2) # 유효 f(1, 2) = 5 # 무효 (SyntaxError)
- 인자 처리: 함수는 인자에 이름을 할당할 수 있지만, 인덱싱 연산은 기본적으로 인덱스를 “있는 그대로” 전달합니다.
class X: def __getitem__(self, index): print(index) x = X() x[0, 1] # (0, 1) 출력 (튜플로 묶여서 전달됨)
- 슬라이스 구문 지원: 파서(parser)의 지원 덕분에 인덱싱 연산은 콜론(
:
) 표기법을 슬라이스로 변환할 수 있습니다.a[1:3]
은 유효하지만f(1:3)
은 유효하지 않습니다. - 0-인자 형태 부재: 함수는
f()
처럼 인자 없는 호출이 가능하지만, 인덱싱은a[]
와 같은 0-인자 형태가 허용되지 않습니다.
5. 세부 사양 (Specification)
이 PEP는 현재의 상태를 확장하여, 위치 인덱스(positional index)와 키워드 인자를 결합하는 향상된 구문을 통해 최종 인덱스(final index)를 생성하는 데 더 많은 유연성을 부여합니다.
주요 사양 내용은 다음과 같습니다:
- 빈 서브스크립트(Empty Subscript)는 여전히 허용되지 않음:
obj[]
는SyntaxError
를 발생시킵니다. - 단일 인덱스 값은 그대로 전달됨:
obj[index]
는type(obj).__getitem__(obj, index)
를 호출합니다. 인덱스 뒤에 키워드가 붙더라도 마찬가지입니다. - 쉼표로 구분된 인자는 튜플로 파싱되어 단일 위치 인자로 전달됨:
obj[spam, eggs]
는type(obj).__getitem__(obj, (spam, eggs))
를 호출합니다.- 위 두 사항은 키워드 인자를 지원하지 않으려는 클래스에 대해 하위 호환성을 완벽하게 보장합니다.
- 키워드 인자는 위치 인자 뒤에 와야 함:
obj[1, 2, spam=None, 3]
은SyntaxError
를 발생시킵니다. 이는 함수 호출의 규칙과 동일합니다. - 키워드 서브스크립트(Keyword Subscripts)는 함수 호출과 유사하게 처리됨:
# 키워드를 포함한 단일 인덱스 obj[index, spam=1, eggs=2] # type(obj).__getitem__(obj, index, spam=1, eggs=2) 호출 # 키워드를 포함한 쉼표로 구분된 인덱스 obj[foo, bar, spam=1, eggs=2] # type(obj).__getitem__(obj, (foo, bar), spam=1, eggs=2) 호출
- 단일 위치 인덱스는 키워드 인자가 추가되더라도 튜플로 변환되지 않습니다.
__setitem__
의 경우, 인덱스와 값의 순서는 동일하게 유지되며 키워드 인자는 함수 정의에서와 같이 맨 끝에 옵니다.
- 키워드 서브스크립트에도 함수 호출과 동일한 규칙 적용: 인자 매칭, 중복 사용 방지, 기본값 할당,
**kwargs
처리 등이 동일하게 적용됩니다. - 시퀀스 언패킹(Sequence Unpacking) 허용:
obj[*items]
와 같은 표기법을 허용합니다.obj[1, *(2, 3), *(4, 5), 6, foo=5] # obj[(1, 2, 3, 4, 5, 6), foo=3)와 동일
- 단일 요소 시퀀스 언패킹은 단일 인자가 전달된 것처럼 동작하지 않고 항상 튜플로 처리됩니다.
- 중요: 시퀀스 언패킹이 없는 경우, 단일 위치 인덱스는
obj[1, foo=5]
와 같이 “있는 그대로” (1
) 전달되지만, 시퀀스 언패킹이 있는 경우 (obj[1, *(), foo=5]
), 결과 요소 수와 관계없이 인덱스는 튜플 ((1,)
)이 됩니다.
- 딕트 언패킹(Dict Unpacking) 허용:
obj[index, **items]
와 같은 표기법을 허용합니다. - 키워드 전용 서브스크립트(Keyword-only Subscripts) 허용:
obj[spam=1, eggs=2]
와 같이 위치 인덱스 없이 키워드 인자만 사용하는 경우, 위치 인덱스는 빈 튜플(()
)이 됩니다. - 키워드 인자에 슬라이스 구문 허용:
obj[3:4, spam=1:4, eggs=2]
와 같이 키워드 인자의 값으로 슬라이스를 사용할 수 있도록 합니다. 이는 일반 함수 호출에도 같은 문법을 허용할 가능성을 열어주지만, 이 PEP의 권장 사항에는 포함되지 않습니다. - 키워드 인자에 기본값 허용:
__getitem__
메서드에 기본값이 있는 경우, 해당 인자를 생략하고 호출할 수 있습니다. __class_getitem__
에도 동일한 의미론 확장: PEP 560 이후 타입 힌트가 작동하는 방식과 유사하게list[T=int]
와 같은 구문이 허용됩니다.
표준 클래스에서의 인덱싱 동작 (Indexing behavior in standard classes)
이 PEP에서 제안된 내용은 dict
, list
등 현재 인덱싱을 사용하는 코어 클래스의 동작을 변경하지 않습니다. 즉, d
가 dict
일 때 d[1, a=2]
와 같은 문장은 TypeError
를 발생시키며, 표준 라이브러리 클래스들은 키워드 인자를 계속해서 지원하지 않습니다.
6. 예외 상황 및 주의사항 (Corner case and Gotchas)
새로운 문법 도입 시 발생할 수 있는 몇 가지 특이 케이스와 주의사항은 다음과 같습니다:
- 인자 이름 중복: 클래스가
def __getitem__(self, index):
와 같이 정의되어 있을 때obj[3, index=4]
나obj[index=1]
와 같이 호출하면,index
인자에 두 개의 값이 전달되어TypeError
가 발생합니다. 이는 기존 클래스에도 소급 적용되므로 하위 호환성 문제는 없습니다. __getitem__
메서드 서명:def __getitem__(self, index, direction='north')
와 같은 서명에서obj[0, 'south']
를 호출하면 예상과 달리type(obj).__getitem__(obj, (0, 'south'), direction='north')
가 호출될 수 있습니다. 이러한 혼란을 피하기 위해 키워드 서브스크립트는 가능한 한 키워드 전용(*
)으로 플래그를 지정하는 것이 모범 사례로 권장됩니다:def __getitem__(self, index, *, direction='north')
.- 단일 인덱스와 키워드 인자:
d[1, a=3]
는__getitem__(d, 1, a=3)
으로 처리되며,__getitem__(d, (1,), a=3)
으로 튜플로 변경되지 않습니다. 키워드 인자가 추가되었다고 해서 전달되는 인덱스의 타입이 변경되는 것은 혼란을 야기할 수 있기 때문입니다. 튜플을 명시적으로 전달해야 하는 경우obj[(1,), a=3]
와 같이 괄호를 사용해야 합니다. - 괄호 생략 규칙의 변화: 키워드 인자가 있을 경우,
obj[1,]
이obj[(1,)]
의 축약형이듯이, 튜플을 나타내는 바깥쪽 괄호를 생략하는 규칙이 더 이상 유효하지 않을 수 있습니다.
7. 대안 (Workarounds)
이 PEP가 해결하려는 문제를 기존 Python 언어 사양에서 어떻게 처리할 수 있는지에 대한 대안(workarounds)도 제시되었습니다:
- 메서드 호출:
x.getitem(1, 2, a=3, b=4)
와 같이 명시적인 메서드를 호출할 수 있습니다. 그러나setitem
의 경우x.setitem(1, 2, a=3, b=4) = val
와 같이 할당할 수 없는 문법적인 한계가 있습니다. - 헬퍼 클래스 사용:
H(1, 2, a=3, b=4)[x]
와 같이 헬퍼 클래스를 사용하여 컨테이너와 인자의 역할을 바꿀 수 있습니다. 이 방식은getitem
,delitem
,setitem
모두에 작동합니다. - 헬퍼 함수 사용:
x[P(1, 2, a=3, b=4)] = val
와 같이 헬퍼 함수를 사용하여 인자들을 단일 객체에 저장하고 인덱스로 전달할 수 있습니다. - 슬라이스 구문 대안:
s[lo:hi:step]
와 같이 슬라이스를 처리하는 헬퍼 객체를 정의하여 유사한 기능을 구현할 수 있습니다.
8. 거부된 아이디어 (Rejected Ideas)
이 PEP를 논의하는 과정에서 여러 아이디어가 제안되었지만, 대부분은 복잡성, 성능 저하, 하위 호환성 문제 또는 불분명한 의미론 때문에 거부되었습니다. 주요 거부된 아이디어는 다음과 같습니다:
- 이전 PEP 472의 해결책: PEP 472에 제시된 대부분의 아이디어는 현재 제안된 방식보다 열등하다고 판단되어 거부되었습니다.
- 새로운 Dunder 메서드 추가 (
__getitem_ex__
등):__getitem_ex__
와 같은 새로운 Dunder 메서드를 도입하여 키워드 인자 지원을 명확히 하자는 제안도 있었습니다. 그러나 이는 서브스크립트 성능 저하, 메커니즘 복잡성 증가, 긴 전환 기간 필요,__setitem_ex__
의 어색한 서명 등의 문제로 거부되었습니다. - 어댑터 함수 추가: “새로운 스타일” 인덱싱을 “오래된 스타일” 인덱싱으로 변환하는 사전 함수를 호출하는 방식도 유사한 문제로 거부되었습니다.
- 새로운 “kwslice” 객체 생성: 키워드 인자를 수동으로 파싱해야 하는 번거로움과 모든 키워드 인자를 무조건 수용하게 되는 문제로 거부되었습니다.
- 단일 비트(Bit)를 사용하여 동작 변경:
__keyfn__ = True
와 같은 특별한 클래스 Dunder 플래그를 사용하여__get|set|delitem__
의 서명을 “함수와 유사하게” 변경하는 제안도 있었습니다. 이는 다른 Dunder의 특정 값에 따라 Dunder 메서드의 서명이 달라지는 기이한 동작으로 인해 거부되었습니다. 정적 타입 체커와 인간 모두에게 혼란을 줄 것이라는 이유였습니다. - 빈 인덱스 표기법 허용 (
obj[]
):obj[]
를obj[()]
와 동일하게 허용하자는 제안도 있었으나, 현재는 문법 에러로 유지하고 향후 추가 PEP에서 논의하기로 결정되었습니다. - 위치 인덱스가 주어지지 않았을 때의 Sentinel 값:
obj[k=3]
와 같이 키워드 인자만 있는 경우, 인덱스 위치에 어떤 값을 전달할지에 대한 논의가 있었습니다.None
,NotImplemented
, 새로운 Sentinel 객체(NoIndex
) 등이 고려되었지만, 최종적으로 빈 튜플(()
)을 전달하는 것으로 결정되었습니다. 이는 NumPy 커뮤니티의 의견과 인자 없는 함수 호출(foo(k=3)
->() {'k': 3}
)의*args
동작과 유사하다는 점이 고려되었습니다.
9. 일반적인 반대 의견 (Common objections)
- “그냥 메서드 호출을 사용해라”: 타입 힌트와 같이 인덱싱이 독점적으로 사용되는 경우나, 배열에서 흔히 사용되는 슬라이스 표기법은 메서드 호출로 대체할 수 없습니다. 또한,
f(1, x=3) = 5
와 같은setitem
유사한 할당이 불가능합니다.
10. 결론 (Resolution)
PEP 637은 Python 인덱싱 연산에 키워드 인자를 도입하려는 야심찬 제안이었지만, 최종적으로 거부되었습니다. 새로운 문법을 도입하는 복잡성과 비용이, 그것이 가져올 이점보다 크다는 것이 핵심적인 거부 사유였습니다. 이 결정은 Python 언어의 안정성과 일관성을 유지하려는 노력의 일환으로 볼 수 있습니다.
* 단일 요소 시퀀스 언패킹은 단일 인자가 전달된 것처럼 동작하지 않고 항상 튜플로 처리됩니다.
* 중요: 시퀀스 언패킹이 없는 경우, 단일 위치 인덱스는 obj[1, foo=5]
와 같이 “있는 그대로” (1
) 전달되지만, 시퀀스 언패킹이 있는 경우 (obj[1, *(), foo=5]
), 결과 요소 수와 관계없이 인덱스는 튜플 ((1,)
)이 됩니다 [cite: 1].
- 딕트 언패킹(Dict Unpacking) 허용:
obj[index, **items]
와 같은 표기법을 허용합니다. - 키워드 전용 서브스크립트(Keyword-only Subscripts) 허용:
obj[spam=1, eggs=2]
와 같이 위치 인덱스 없이 키워드 인자만 사용하는 경우, 위치 인덱스는 빈 튜플(()
)이 됩니다. - 키워드 인자에 슬라이스 구문 허용:
obj[3:4, spam=1:4, eggs=2]
와 같이 키워드 인자의 값으로 슬라이스를 사용할 수 있도록 합니다. 이는 일반 함수 호출에도 같은 문법을 허용할 가능성을 열어주지만, 이 PEP의 권장 사항에는 포함되지 않습니다 [cite: 1]. - 키워드 인자에 기본값 허용:
__getitem__
메서드에 기본값이 있는 경우, 해당 인자를 생략하고 호출할 수 있습니다. __class_getitem__
에도 동일한 의미론 확장: PEP 560 이후 타입 힌트가 작동하는 방식과 유사하게list[T=int]
와 같은 구문이 허용됩니다 [cite: 1].
표준 클래스에서의 인덱싱 동작 (Indexing behavior in standard classes)
이 PEP에서 제안된 내용은 dict
, list
등 현재 인덱싱을 사용하는 코어 클래스의 동작을 변경하지 않습니다. 즉, d
가 dict
일 때 d[1, a=2]
와 같은 문장은 TypeError
를 발생시키며, 표준 라이브러리 클래스들은 키워드 인자를 계속해서 지원하지 않습니다 [cite: 1].
6. 예외 상황 및 주의사항 (Corner case and Gotchas)
새로운 문법 도입 시 발생할 수 있는 몇 가지 특이 케이스와 주의사항은 다음과 같습니다 [cite: 1]:
- 인자 이름 중복: 클래스가
def __getitem__(self, index):
와 같이 정의되어 있을 때obj[3, index=4]
나obj[index=1]
와 같이 호출하면,index
인자에 두 개의 값이 전달되어TypeError
가 발생합니다. 이는 기존 클래스에도 소급 적용되므로 하위 호환성 문제는 없습니다. __getitem__
메서드 서명:def __getitem__(self, index, direction='north')
와 같은 서명에서obj[0, 'south']
를 호출하면 예상과 달리type(obj).__getitem__(obj, (0, 'south'), direction='north')
가 호출될 수 있습니다. 이러한 혼란을 피하기 위해 키워드 서브스크립트는 가능한 한 키워드 전용(*
)으로 플래그를 지정하는 것이 모범 사례로 권장됩니다:def __getitem__(self, index, *, direction='north')
.- 단일 인덱스와 키워드 인자:
d[1, a=3]
는__getitem__(d, 1, a=3)
으로 처리되며,__getitem__(d, (1,), a=3)
으로 튜플로 변경되지 않습니다. 키워드 인자가 추가되었다고 해서 전달되는 인덱스의 타입이 변경되는 것은 혼란을 야기할 수 있기 때문입니다. 튜플을 명시적으로 전달해야 하는 경우obj[(1,), a=3]
와 같이 괄호를 사용해야 합니다. - 괄호 생략 규칙의 변화: 키워드 인자가 있을 경우,
obj[1,]
이obj[(1,)]
의 축약형이듯이, 튜플을 나타내는 바깥쪽 괄호를 생략하는 규칙이 더 이상 유효하지 않을 수 있습니다.
7. 대안 (Workarounds)
이 PEP가 해결하려는 문제를 기존 Python 언어 사양에서 어떻게 처리할 수 있는지에 대한 대안(workarounds)도 제시되었습니다 [cite: 1]:
- 메서드 호출:
x.getitem(1, 2, a=3, b=4)
와 같이 명시적인 메서드를 호출할 수 있습니다. 그러나setitem
의 경우x.setitem(1, 2, a=3, b=4) = val
와 같이 할당할 수 없는 문법적인 한계가 있습니다. - 헬퍼 클래스 사용:
H(1, 2, a=3, b=4)[x]
와 같이 헬퍼 클래스를 사용하여 컨테이너와 인자의 역할을 바꿀 수 있습니다. 이 방식은getitem
,delitem
,setitem
모두에 작동합니다. - 헬퍼 함수 사용:
x[P(1, 2, a=3, b=4)] = val
와 같이 헬퍼 함수를 사용하여 인자들을 단일 객체에 저장하고 인덱스로 전달할 수 있습니다. - 슬라이스 구문 대안:
s[lo:hi:step]
와 같이 슬라이스를 처리하는 헬퍼 객체를 정의하여 유사한 기능을 구현할 수 있습니다.
8. 거부된 아이디어 (Rejected Ideas)
이 PEP를 논의하는 과정에서 여러 아이디어가 제안되었지만, 대부분은 복잡성, 성능 저하, 하위 호환성 문제 또는 불분명한 의미론 때문에 거부되었습니다 [cite: 1]. 주요 거부된 아이디어는 다음과 같습니다:
- 이전 PEP 472의 해결책: PEP 472에 제시된 대부분의 아이디어는 현재 제안된 방식보다 열등하다고 판단되어 거부되었습니다.
- 새로운 Dunder 메서드 추가 (
__getitem_ex__
등):__getitem_ex__
와 같은 새로운 Dunder 메서드를 도입하여 키워드 인자 지원을 명확히 하자는 제안도 있었습니다. 그러나 이는 서브스크립트 성능 저하, 메커니즘 복잡성 증가, 긴 전환 기간 필요,__setitem_ex__
의 어색한 서명 등의 문제로 거부되었습니다 [cite: 1]. - 어댑터 함수 추가: “새로운 스타일” 인덱싱을 “오래된 스타일” 인덱싱으로 변환하는 사전 함수를 호출하는 방식도 유사한 문제로 거부되었습니다 [cite: 1].
- 새로운 “kwslice” 객체 생성: 키워드 인자를 수동으로 파싱해야 하는 번거로움과 모든 키워드 인자를 무조건 수용하게 되는 문제로 거부되었습니다 [cite: 1].
- 단일 비트(Bit)를 사용하여 동작 변경:
__keyfn__ = True
와 같은 특별한 클래스 Dunder 플래그를 사용하여__get|set|delitem__
의 서명을 “함수와 유사하게” 변경하는 제안도 있었습니다. 이는 다른 Dunder의 특정 값에 따라 Dunder 메서드의 서명이 달라지는 기이한 동작으로 인해 거부되었습니다. 정적 타입 체커와 인간 모두에게 혼란을 줄 것이라는 이유였습니다 [cite: 1]. - 빈 인덱스 표기법 허용 (
obj[]
):obj[]
를obj[()]
와 동일하게 허용하자는 제안도 있었으나, 현재는 문법 에러로 유지하고 향후 추가 PEP에서 논의하기로 결정되었습니다 [cite: 1]. - 위치 인덱스가 주어지지 않았을 때의 Sentinel 값:
obj[k=3]
와 같이 키워드 인자만 있는 경우, 인덱스 위치에 어떤 값을 전달할지에 대한 논의가 있었습니다.None
,NotImplemented
, 새로운 Sentinel 객체(NoIndex
) 등이 고려되었지만, 최종적으로 빈 튜플(()
)을 전달하는 것으로 결정되었습니다. 이는 NumPy 커뮤니티의 의견과 인자 없는 함수 호출(foo(k=3)
->() {'k': 3}
)의*args
동작과 유사하다는 점이 고려되었습니다 [cite: 1].
9. 일반적인 반대 의견 (Common objections)
- “그냥 메서드 호출을 사용해라”: 타입 힌트와 같이 인덱싱이 독점적으로 사용되는 경우나, 배열에서 흔히 사용되는 슬라이스 표기법은 메서드 호출로 대체할 수 없습니다. 또한,
f(1, x=3) = 5
와 같은setitem
유사한 할당이 불가능합니다 [cite: 1].
10. 결론 (Resolution)
PEP 637은 Python 인덱싱 연산에 키워드 인자를 도입하려는 야심찬 제안이었지만, 최종적으로 거부되었습니다. 새로운 문법을 도입하는 복잡성과 비용이, 그것이 가져올 이점보다 크다는 것이 핵심적인 거부 사유였습니다 [cite: 1]. 이 결정은 Python 언어의 안정성과 일관성을 유지하려는 노력의 일환으로 볼 수 있습니다.
⚠️ 알림: 이 문서는 AI를 활용하여 번역되었으며, 기술적 정확성을 보장하지 않습니다. 정확한 내용은 반드시 원문을 확인하시기 바랍니다.
Comments