파이썬의 매력이 self를 쓰는 거라고 생각해요

종종 파이썬에 대한 평을 인터넷에서 한 번씩 검색해 보는데요. 많은 분들이 가장
많이 싫어하는 것은 뭐니뭐니 해도 "들여쓰기 강제"겠죠. 뭐 이거야 취향 문제라
어쩔 수 없는 것이고. 사실 파이썬 사용자들 중에서 "들여쓰기 강제"를 좋아하는 사람이
많기 때문에 파이썬의 원래 목적에도 더 맞다고 생각되고… ^.^;

그에 못지않게 자주 지적되는 것이, 객체 안에서 꼭 self.를 달아 줘야 된다는 것인데요.
저는 self.를 항상 명시적으로 붙이는 거야말로 파이썬의 참 매력이고, self가 없어지면
파이썬이 무너진다고 생각합니다! 특히 자바 프로그래머들이 파이썬의 self에 대해
많이 지적하는데, 자바와 파이썬 모두에서 영향력이 있는 브루스 엑켈도 self를
(메쏘드 선언에서만이라도) 없애보자
했는데, 그에 대한 응답으로 귀도가 불가능한 일이다라고
그 이유를 논리적으로 설명했었습니다.

브루스 엑켈의 제의가 선언에서만 없애자는 것이었기 때문에, 메쏘드 내부의 코드에서
없애면 안 되는 이유에 대해서는 귀도가 설명하지 않았는데요. 브루스 엑켈이 스스로 결론 내린
그 앞 부분의 문제 "self가 왜 있어야 하냐!" 그 이유에 대해서 좀 설명해서
자바 프로그래머 분들이 파이썬을 좀 더 이해할 수 있도록 도와볼까 합니다.

파이썬에서 self가 붙게 된 역사적인 이유는 파이썬의 클래스 내 메쏘드는 기본적으로
외부에 독립되어 있는 함수에 껍데기를 씌운 것이기 때문입니다. 자바는 아예 독립 함수가 없고,
다른 언어에서는 대체로 독립된 함수들과 메쏘드는 다른 취급을 받는데, 파이썬에서는 그냥
함수를 메쏘드로 편입시켜서 쓸 수도 있고, 둘을 비슷한 방법으로 바꿔서 다룰 수 있습니다.
예를 들면 이런 코드가 가능하겠죠.

밖에서 선언된 함수를 클래스 정의할 때 메쏘드로 끌어들인 것이죠. 메타클래스를 쓴다면 더
동적으로 해 버릴 수도 있습니다. 도대체 이런 코드를 뭐에 쓰냐! 하는 의문을 가지실 수도 있는데요.
의외로 이런 기술이 많이 쓰입니다. egg함수를 C로 구현된 확장모듈에서 끌여들일 수도 있고요.
egg만 사용자가 구현할 수 있도록 노출시켜서 외부 모듈에서 불러올 수도 있고요. 심지어
R이나 .NET같은 브릿지에서 다른 언어로 구현된 것을 쓸 수도 있습니다. 메쏘드가 결국
함수기반이라는 것은 생각보다 강력한 개념으로, __로 시작하는 내부 속성을 쓰면 더욱 희한한 것도
제어할 수 있게 되고, 클래스를 안 쓴 코드와 클래스를 쓰는 코드 사이를 넘나들거나 점진적으로 변경할 때 아주 쓸모가 있습니다.

파이썬에서 instance.method(A, B) 는 class.method(instance, A, B) 와 같은 역할을 합니다.
이것은 함수가 메쏘드가 된 얘기 외에도, 다중상속을 받았거나 이름이 중복되는 메쏘드를 부를 때 쓰이기도 하고, 다양하게 상속받은 하위 인스턴스들을 명시적으로 한 메쏘드에게 콕 찝어 줄 때도 쓰이고, 이 규칙 하나가 수많은 모호함을 해결해 줍니다. 그래서 이 일관성이 문법 전반에 계속 흐르고 있습니다.

그렇다면 그냥 함수는 함수로 쓰고 메쏘드는 메쏘드로 쓰고 같은 데서 상속받으면 비슷한 인터페이스가
나올 수 있지 않겠느냐 하는 의문이 있을 수도 있습니다. self의 또 다른 존재 이유로 파이썬을 파이썬으로
만드는 가장 중요한 특징인 "네임스페이스"가 등장합니다.

"네임스페이스"는 파이썬에서 변수를 담아두는 공간으로, 원래는 로컬, 모듈 전체, 빌트인 세 가지 네임스페이스를 찾도록 되어 있다가, 파이썬 2.1부터 상위에 싸여있는 것들도 찾도록 돼 있습니다. 이해를 돕기 위해 예를 들어드리면

이런 파일이 있다면 A는 모듈 전체, 나머지는 로컬에 들어갑니다. 그런데 Y()의 입장에서 C는 로컬인데, B와 D는 자기 로컬은 아니면서 상위 네임스페이스에 속한 변수들이 됩니다. 따라서, 파이썬 2.1부터는 모듈 전체로 가기 전에 B, D가 있는 X영역부터 찾습니다. 파이썬은 변수 선언을 하지 않기 때문에, 변수의 네임스페이스는 대입이 한 번이라도 일어난 최소의 네임스페이스에 영역을 잡는데요. 위에서 C는 Y()안에서 대입이 있었기 때문에 Y()안의 네임스페이스에 잡히고, B, D는 X()에서 대입이 있기 때문에 X()의 네임스페이스에 잡힙니다. 그런데, A는 대입이 모듈에서만 있고, X()에는 없어서 X() 로컬이 아니라 글로벌로 잡힙니다.
이런 네임스페이스를 바꿔주는 키워드가 원래부터 지원되는 global과 파이썬 3.0부터 지원되는 nonlocal이 있습니다. 이건 따로 관심이 있으시면 매뉴얼을 보시면 되겠습니다. +_+

여기서 갑자기 웬 네임스페이스 설명을 self하는 데 하느냐! 하면..

self.을 생략하게되면 로컬 네임스페이스와 인스턴스 네임스페이스가 섞이게 된다는 것입니다. 즉 클래스에서 x = 1하면 이게 로컬로 갈 지, 인스턴스로 갈지 모호해 지는거죠. 자바나 C++은 명시적으로 선언을 하기 때문에 헷갈리지 않지만, 파이썬은 선언을 않기에 명시적으로 쓸 필요가 있죠. 그래서 펄이나 루비에서는 따로 @나 !같은 기호를 도입해서 쓰는데.. 파이썬의 원칙 중 매우 중요한 것으로 "연산자 너무 늘리지 말자"가 있어서 고려 대상은 아닙니다. self.라고 쓰면 파이썬 문법을 모르는 사람도 아 이게 뭐구나! 하고 추측을 할 수 있지만 @같은 걸 붙여놓으면, 문법책을 참조하거나 고난도의 눈치를 보지 않고서는 인스턴스 네임스페이스인지, 클래스 네임스페이스인지, 글로벌 네임스페이스인지 알기가 힘들겠죠.

그럼 또 제기될 수 있는 의문! 대입은 그럼 명시적으로 하고, 쓸 때만 인스턴스와 클래스도 한 번 타 주면 되지 않겠니? 하고 소극적인 부탁을 해 볼 수도 있겠는데요. 읽는 방법, 쓰는 방법이 다른 건 아무래도 파이썬 원칙에는 맞지 않고, 속도도 많이 느려집니다.

모호한 것을 보면, 추측할 수 있을 거라는 유혹은 단호하게 거절한다. (In the face of ambiguity, refuse the temptation to guess.) — 팀 피터스, 파이썬의 선(Zen)

Watch movie online The Transporter Refueled (2015)

18 thoughts on “파이썬의 매력이 self를 쓰는 거라고 생각해요”

  1. 저도 자바를 하다가 파이썬으로 넘어왔을 때에는 뭐하러 이 수많은 self들을 직접 달아줘야하나 했는데, 지금은 오히려 C++이나 Java를 보면 이게 그냥 변수인지 멤버인지 헷갈리더라구요.

    타이핑이 조금 늘긴 하지만 명시적으로 써주는게 좋은 것 같습니다. 🙂

  2. 파이썬을 시작한지 일주일 쯤 된 초보입니다.
    self 가 짜증나요! 라고 파이썬을 원래 하시던 다른 분에게 불평했더니
    여기 링크를 주시더라고요.

    제 생각은 이렇습니다.
    self. 를 쓰는 것은 어디까지나 선언을 하지 않음으로서 생기는
    “어쩔 수 없는” 불필요한 작업일 뿐이고, “매력” 이라고 칭할 수 있는 것은
    아니라고 봅니다.

    첫번째 들어 주셨던 예는 self 를 사용하지 않고서도 얼마든지
    예쁘게 구현 할 수 있습니다.
    물론 정확히 같은 메커니즘은 아니겠습니다만,
    위에 “생각보다 강력” 하다고 지적하신 것은
    오히려 클래스의 독립성을 훼손하는 행위라고 생각합니다.

    사실 저는 어떤가 하면, self가 “싫긴” 하지만,
    self가 싫다기 보다는. self가 존재 할 수 밖에 없는 python의 구조가 싫은 겁니다

    선언에서 self가 빠져버리면, 삽질 할 사람 많을 것 같습니다 -_-;
    실제로 며칠전에. 클래스 멤버라는 개념을 모르고 코딩하다가
    (당연히 인스턴스의 멤버일 줄..) 한나절을 그냥 날린 적이 있기도 하고요.

  3. 고빈섭님:
    self를 어쩔 수 없는 짐으로 볼 수도 있지만, 들여쓰기 강제처럼 긍정적인 효과가 생각보다 많습니다. self.가 항상 달려있어서 코드를 잘 모르는 사람이 선언부를 보지 않고도 어디에 속하는 것인지 알 수 있고, 코드를 읽을 때 깔끔하게 읽힙니다. 즉, self가 없으면 헝가리안 표기법 같은 이상한 것을 동원하지 않으면 영어로 순서대로 읽었을 때 인스턴스를 조작한다는 느낌을 갖기가 쉽지 않은데, self를 명시적으로 써 주면 순서대로 영어로 읽을 수 있어서 코드가 훨씬 읽기 쉬워지는 경우가 많습니다.

    클래스의 독립성 부분은, 파이썬은 사실 순수성과는 거리가 먼 언어입니다. 누구나 마음대로 할 수 있어야할 들여쓰기를 강제로 시키지를 않나, 클래스 상속에서 네임스페이스 숨기기 같은 것도 그냥 감춰놓는 척만 하지, 접근이 불가능한 것은 아닙니다. 실용적인 언어로 클래스의 독립성은 파이썬에서는 필요없는 것이기에 웬만한 작업은 대부분 열려있습니다. “대규모 프로젝트”에서 그런 것을 강제할 일이 필요하다면, 많은 규약들이 메타클래스나 클래스 내부 메쏘드를 오버라이드해서 강제 규칙을 만들 수 있기 때문에 실질적으로 문제가 될 일은 별로 없습니다.

    아마도 파이썬의 구조가 마음에 들지 않으신 것은, 참고하신 책의 문제도 있을 것 같습니다. 동적언어 중에서도 파이썬은 특히 간결하지만 독특한 네임스페이스 체계를 갖추고 있어서 책에서 클래스를 다룰 때는 반드시 네임스페이스를 다뤄야하는데, 일부 책들은 생략하고 보통 C++언어 설명처럼 지나가기도 하는 것 같고요..

    사실 파이썬은 python4ply라는 툴이 나온 이후로 문법을 재정의하기가 매우 쉬워졌습니다. 만약에 쓰시는 프로젝트에서 적용 범위가 비교적 크고, 자바 개발자들이 많이 참여한다면 python4ply로 몇 가지 문법만 손을 봐서 들여쓰기대신 {}로 묶는다던지, self를 생략하게 한다던지 하는 문법 수정해서 쓰실 수도 있습니다~

    의견 감사드리며, 앞으로는 파이썬하고 좋은 경험 있으시길 바랍니다. ^^;

  4. 저도 처음엔 의아했었는데, 계속 쓰다보니 네임스페이스를 넘나들며(?) 작업할 때 명시적으로 있는 것이 좋더라구요. 예로 드신 egg와 같은 경우도 그렇고, 언어의 확장성을 늘려주는 중요한 요소라는 생각이 듭니다.

  5. 강제 들여쓰기는 싫어하는 사람보다 좋아하는 사람이 많고
    메소드 선언에 self는 좋아하는 사람보다 싫어하는 사람이 많다…

    고 추측되는데, 맞을까요?

    파이썬 초보인 저에게 거슬리는 딱 한가지가 바로 메소드 선언에 self 입니다.
    강제 들여쓰기는 매우 좋아라~ 하고요.

  6. 그르르님: 제 생각엔 강제들여쓰기를 싫어하는 분이 훨씬 더 많을 것 같습니다~ 보통 self를 싫어하는 건 자바/C++가 주력인 프로그래머분들인데, 사실 자바/C++ 프로그래머는 자신의 주력 언어로도 웬만큼은 축약해서 쓸 수 있어서 굳이 파이썬을 많이 쓰지 않는 편이라… 선언부에 self를 써야하는 것은 귀도가 말하기를 지금 에러가 좀 헷갈리게 나오는 문제가 있긴 하다고, 에러메시지를 잘 알아볼 수 있게 고쳐야겠다고 얘기를 했습니다. 아마도 다음 버전에서는 에러메시지가 좀 수정이 되겠죠~ 🙂

  7. self를 매번 타이핑하는 것이 불편하다는 분들을 위해:

    If you don’t think carefully, you might think that programming is just typing statements in a programming language. — Ward Cunningham

  8. 저도 처음 접했을 때는 몰랐지만, ruby 쪽을 하면서 비교하다보니, 그렇게 명시적인 점이 좋다고 생각되더군요. 어쨌든… ‘현재 네가 사랑하는 메서드 호출방식이 내일 사랑하는 메서드 호출방식이 아닐지도 몰라’ 이런 느낌으로 살아야 할 것 같아요.

    타이핑하기 불편하다고, 맘에 안든다고 하는 것은, 대체로 다 변명이고, 실무에서 특정 언어의 장단점이 되는 것은 기본 라이브러리나 외부 라이브러리 이런 쪽이죠.

  9. 올해 처음으로 파이썬으로 어느정도 규모의 프로젝트를 진행하면서(개발 기간 5개월) 느낀 점은, 언어마다 문화가 다르고 목적이 다르다는것 같습니다. 파이썬을 C#이나 Java의 문화로 접근하다 보면 이해하기도 어렵고 불필요해 보이는것도 많이 있고요… 오히려 동적 언어를 효과적으로 사용하지 못하게 되는것 같습니다.
    들여쓰기 강제 같은 경우, 처음에는 강제적인 요소가 맘에 안들었지만 익숙해진 후에는 텝을 눌렀을 때 몸과 마음이 다음 블럭으로 진입했다는… 표현하기 어려운데 아마도 블럭안으로 들어갈 때 쉬프트를 누르고 {한다음 }해주는것보다 간결해서이지 싶기도 하고요… 익숙해지기 나름인것 같아요.
    클레스 메소드의 self사용은 좀 어거지 스럽다는 느낌도 지울 수 없긴한데 이것도 익숙해지니 좋드만요. 다 익숙해지기 나름인것 같습니다. 익숙해져도 이상하면 고놈이 이상한거겠지요… ㅎㅎ

  10. 음.. 책이 잘못된건 아니고요 나와있긴 합니다만,
    일반적인 프로그래머라면 새로운 언어가 나온다고 해서
    책을 정독하지는 않을 것 같은데요..

    저의 경우 보통 primitive type, 메모리 사용법, scoping rule, 기본 문법 파트만 간략하게 보고 바로 코딩에 들어가는데요,
    (대부분은 그럴 것이라고 생각하고요)
    매 언어가 나올 때 마다 책을 정독해야 한다면
    프로그래밍 언어론따위를 배운 의미도, 배울 이유도 없겠고요.
    (챕터 제목에 scoping rule 이라고 안 써있고 namespace 라고 써 있어서 C#의 namespace 같은 개념으로 생각하고 그냥 넘겼던듯..)

    장혜식님의 덧글 덕분에
    어렴풋이 파이썬이 싫었던 이유가 좀 명확해 지는 것 같습니다

    procedural language나 OOP language 에 익숙한 사람들에게
    “대충 구조를 이해하고 시작하기 어려운” 부분들이 있고,
    또 “이러면 되겠지” (말씀하신 파이썬의 철학에 위배됩니다만 ^^;)
    라고 생각하고 하는 것들이 warning이나 error 없이 예측하지 못한 결과를 내서
    삽질하게 하는 부분들 이었던 것 같습니다.

    결과적으로 제 공부가 부족했던 것이 문제였던 것 같습니다.
    시간내서 책을 끝까지 정독 해 봐야겠네요.

    허접한 댓글에 답글 달아 주셔서 감사합니다 🙂

  11. 고빈섭:
    아.. 아닙니다. 자바프로그래머들도 배우기 쉬운 언어가 되어야 하는데, 파이썬이 좀 어떤 면에서는 부족한 것 같습니다. 예를 들면 self를 빼먹으면 나오는 이상한 에러메시지나, 메쏘드 인수 개수가 1개씩 줄어들거나 늘어서 에러가 나는 것 같은 건 대부분의 자바, C++ 프로그래머가 크게 당황하는 문제가 아닐까합니다. 🙂 사실 파이썬은 따로 공부를 안 해도 웬만큼은 눈치만 갖고도 할 수 있을만큼 간단한 것도 일부 목표였는데, 기존 프로그래머들이 빨리 할 수 있고, 일관성도 유지하면서 쉽기도 하려니 동시에 달성하기는 좀 힘든 면이 없지 않습니다.

    아마도 자바프로그래머를 위한 파이썬 1페이지로 입문하기 같은 문서가 나오면 좋지 않을까 하고 잠시 생각이.. 🙂

  12. 꺅. “자바프로그래머를 위한 파이썬 1페이지 입문하기” 써주시는건가요? +_+ 이왕이면 시리즈로.. “루비 프로그래머를 위한..” “c# 프로그래머를 위한..” 이런것도..ㅎㅎ

  13. 길게 쓰셨는데, 저의 경우에는 처음부터 너무 잘 와닿는 부분이었습니다.
    솔직히 C (not C++)로 OOP 해 보면 function(object, arg1, …)가 훨씬 익숙하고, class와 object도 헛갈리지 않죠. ^^;;;
    물론 OOP 신도라던가 C++이 macro이던 시절을 겪지 못했다면 이해하기 힘들겠지만…
    (사실 attribute를 선언 안해도 된다(=dict다)는 것이 더 충격이었어요… ㅋㅋㅋ)

  14. > 펄이나 루비에서는 따로 @나 !같은 기호를 도입해서 쓰는데..

    Perl에서 @,!기호가 Ruby에서 처럼 변수의 영역을 나타내는데 쓰이지 않습니다. Perl의 sigil($,@,%등)은 변수의 타입을 나타내는데 쓰입니다. Perl 변수의 영역과 생명주기는 my,our,local과 코드블럭 {}등으로 한정되는 렉시컬영역으로 어느 언어보다 명시적이고 엄격하게 채크됩니다. 그리고 Perl의 객체구현은 래리월이 http://network.hanb.co.kr/view.php?bi_id=1495 란 글에서도 밝혔다시피 Python의 객체 시스템을 이용했다고 했으며 self를 사용하는 방식은 python과 유사합니다만 Perl은 class라는 키워드가 없으므로 네임스페이스를 구분하는 package 자체가 클래스로 사용하며 객체란 어떤 자료(스칼라,배열,해시등)을 담고 있는 레퍼런스에 bless란 함수로 패키지(클래스)이름을 테깅(tagging)함으로써 만들어집니다. Perl의 객체시스템은 아주 기본적인 방법론만 제공하고 Java나 C++에서처럼 클래스관련 키워드들에 의해 객체지향 프로그래밍을 일정한 방식으로 강제하지 않으므로서 아주 유연하게 확장이 가능합니다. 이런 자유도가 Perl의 OOP를 어렵다고 느끼게 하고 다양한 방식의 객체형식의 모듈이 난립하여 어떤 것을 사용해야 할지 갈피를 못잡게 하는 면도 있습니다만 요즘은 규모가 큰 프로젝트에서는 Class::Accessor(http://search.cpan.org/dist/Class-Accessor/)나 Perl 6에서 도입 될 메타오브젝트프로토콜형식 객체구현의 Perl 5구현인 Moose(http://search.cpan.org/dist/Moose/)가 거의 표준으로 사용되고 있습니다. 이런 이유에서 일본의 유명 Perl해커인 Dan kogai씨는 http://www.dan.co.jp/~dankogai/yapcasia2008/psl.html 에서 That’s why you should learn perl if you want to learn OO! You can learn how to make an object system, not just how to use it. 라고 얘기했죠.

  15. 위에 정세일님 말씀에 동감하게 되네요. 자바 위주로 하다가 4달간 파이썬만 쓰게 된 적이 있는데 접근 방법이나 철학이 틀린걸 모르고 자바처럼 접근해서 쓰려고 하다가 뭔가 맞지 않는 느낌을 많이 받았었습니다. 들여쓰기 하나로 로직이 바껴버리는 경우도 있지만 익숙해지면 그것도 나름 괜찮은다는 생각이 들었습니다.

  16. 첨엔 self.를 달아주는게 어색했는데
    지금은 c++ 코드를 짤때 일일이 this-> 를 쳐주고 있습니다.

  17. C++ 를 주력으로 하는 개발자로서 python에 가장 맘에 안 드는게 self. 입니다. 함수 내에서 변수접근에는 local, global, builtin 순서로 암시적인 지칭의 규칙이 있으면서 클래스 멤버에는 명시적인 지칭이 필요하다니 이런게 무슨 일관성인가요? 그리고 타이핑하기 힘든 것보다는 근본적인 문제는 코드를 산문처럼 읽히도록 아름답게 써나가야 하는데 이를 수많은 self들이 심각하게 방해한다는 점입니다.

Comments are closed.