Guido가 몇 년째 열심히 반대하다가 얼마전에 드디어 들어간 list.sorted와 얼마전 블로그에서 얘기했던 itertools.groupby에서 아주 유용한 itemgetter와 attrgetter가 얼마전에 추가됐습니다. 원래 lambda로 처리해야하는 건데 아무래도 lambda만 들어가면 일단 거부감이 들기 때매.. 흐흐…
예를 들면 원래 [(10, “merong”), (20, “hoho”), (30, “abcd”)]를 순서대로 정렬하려면
1 2 3 4 |
>>> x = [(10, "merong"), (20, "hoho"), (30, "abcd")] >>> x.sort(lambda x,y: cmp(x[1],y[1])) >>> x [(30, 'abcd'), (20, 'hoho'), (10, 'merong')] |
이렇게 됐는데, 파이썬 2.4에서는 이렇게 처리하면 됩니다. (미리 from operator import itemgetter 한 상태)
1 2 |
>>> list.sorted([(10, "merong"), (20, "hoho"), (30, "abcd")], key=itemgetter(1)) [(30, 'abcd'), (20, 'hoho'), (10, 'merong')] |
므흐흐.. 좋기는 한데, 뭔가 itemgetter랑 attrgetter는 너무 한군데만 특수화되었다는 느낌을 지울 수 없는데, 다시 메일링 리스트에 Michael W. Hudson이 엄청난 팁을 하나 공개했는데, 요렇게 쓴다고 합니다. (정확히는 이 코드는 Thomas Heller가 mwh의 사용법을 보고 추리해서 짠 것..)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Adder: def __init__(self, number): self._number = number def __call__(self, arg): return arg + self._number class X: def __add__(self, number): return Adder(number) X = X() print map(X + 1, range(2)) |
즉, X + 1 하면 + 1하는 순간에 Adder인스턴스가 생성돼서, +1하는 객체로 둔갑을 해서 결국 웬만한 것은 lambda 없이도 쓸 수 있게 된다는.. 크크 정말 멋지네요 +_+. 그런데, 이 방법에서는 X.split(‘.’) 같이 아래 어트리뷰트를 호출하는 건 코드가 실행되는 때가 먼저 와 버리기 때문에 제대로 동작하지 못하게 되는데, 몇가지 껍데기를 씌우면 되기는 되겠네요..
음.. 하여간 대부분의 경우에 정말 멋지게 동작해서 mwh의 이 아이디어는 아주 멋져보입니다.~
(덧붙임: 나중에 리스트에 다른 사람이 이걸 파이썬으로 구현한 소스를 올려놨네요. http://www.sil-tec.gr/~tzot/predicates.py 에서 받을 수 있습니다.)
X는 정말 굉장한 아이디어네요. lambda o: o.value[1] 같은 걸 X.value[1]로 쓸 수 있다는 거죠? Boost의 lambda와 비슷해 보이기도 하고…
참고: boost::lambda의 예. for_each(seq.begin(), seq.end(), cout << *_1 << ‘\n’); _1이 X 같은 역할을 합니다.
요즘의 파이썬 이슈는 점점 알 수 없는 것들만 늘어나요..
흑.
feanor: 오.. boost::lambda는 C++에 있는 것인가요?
hey: 음.. 사실 개발 버전의 변경사항들은 중간에 빠지는 것도 엄청 많기 때문에, 나중엔 다 쉬워져요 으흐흐 =3
퍼키: boost::lambda는 무시무시한 C++ 템플릿 hack이구요, 문서는 http://boost.org/libs/lambda/doc/ 에 있습니다.
흐음, 결국 python-dev 에도 boost::lambda와 같은 아이디어가 나왔군요. 이 메일 http://mail.python.org/pipermail/python-dev/2003-December/040687.html
에서 주장하고 있는 &1, &2가 정확히 그겁니다.
아무래도 문법을 고치면서까지 확장하려고 하지는 않을 듯 하네요.. 제 생각으로는 Extractor 클래스가 도입되지 않을까 하는..
저 X는 제가 만들어 쓰고 있는 것과 비슷하네요.
일종의 Dynamic Mock 객체 같은 것인데(원래 출발은 테스트 하니스 목적), X에 행해진 computation을 모두 기억하고 있다가 나중에 X 값이 정해지면 전체 값이 계산되는 뭐 그런 것입니다.
예를 들어,
f=(X*2-3)/2.0
print f(3) -> 1.5
오오.. 역시 김창준님은 벌써 쓰고 계셨군요.. 🙂
무비조아
무비조아
와~ 이것 참 편하네요. 감사~~ +_+
와 시험 잘 보세요 ^^
감사감사 ^.^
생각만해도 아찔하군요. 면역학!!! ㄷㄷㄷ