Introduction
Pythonic 한 코드란 무엇일까?
본인은 pythonic 한 코드란 파이썬의 특징적인 기능들을 잘 살리면서 파이썬의 철학에 맞게 작성한 코드라고 두루뭉술하게 알고 있었고, 이전 포스트에서도 굉장히 여러 번 pythonic이란 단어를 언급했었다.
하지만 막상 pythonic 하다는 것이 정확히 어떤 것을 뜻하는지 인지하고 있나 생각 해 보니, 그렇지 않다는 것을 깨달았다.
따라서 이번 포스팅에서는 Pythonic 한 코드에 대해서 알아보도록 하겠다.
What is Pythonic?
Pythonic 하다는 표현에 대한 설명은 꽤나 다양한 버전이 존재한다.
1. 파이썬 언어의 특징적인 기능들을 이용해 보기 좋은 / 명확한 / 유지보수가 쉬운 코드를 작성하는 것,
2. 파이썬 커뮤니티의 컨벤션을 잘 따르며 언어를 처음 의도된 방향으로 올바르게 사용하는 것
3. ...
..등등 여러 가지의 해석이 있는데, 이들 모두 흔히 받아들여지고 쓰이는 pythonic 이란 단어의 의미에 부합하는 표현이라고 생각한다. 하지만 이들의 공통적인 본질을 따라가 보면, 최종적으로는 파이썬의 철학인 The Zen of Python 에 도달하게 된다. Pythonic 함을 지키는 것이 바로 Zen of Python을 따르는 것이라고 보면 된다.
그렇다면 Zen of Python 이란 것은 대체 무엇일까?
The Zen of Python
파이썬에는 이스터에그가 하나 숨겨져 있는데, 바로 this, 즉 자기 자신을 임포트 하는 것이다.
import this
위 코드를 실행하면 긴 텍스트가 하나 출력된다.
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>>
첫 줄에서도 볼 수 있듯이, 이것이 바로 Zen of Python이다.
TMI로, this 모듈에는 this.i, this.c, this.d, this.s 프로퍼티 네 개가 존재하는데 s는 ROT-13 매핑으로 인코딩된 텍스트, d는 이걸 해독하기 위한 딕셔너리, 그리고 i와 c는 단순히 루프를 돌기 위한 인덱스 변수이다. 그리고 일종의 조크로, 모듈 내의 코드에는 각 격언들을 어기는 부분이 한 번씩은 등장한다. (정말 TMI다)
Python의 초기 기여자인 Tim Peters (Pythoneer 라고 부르는 것 같다...) 가 작성한, 파이썬을 이용한 프로그래밍 시 따라야 할 기본 철학 20가지를 다루고 있다. 사실 적힌 건 19가지 밖에 없는데, 마지막 20번째 격언을 파이썬의 창시자인 Guido van Rossum 이 채우도록 남겨 두었으나 아직까지도 공란으로 남아있다고 한다.
전부 다 짚어보기보다는 대표적인 것들을 한번 살펴보자.
▣ Beautiful is better than ugly
될 수 있으면 보기 좋게 만들라는 뜻으로, 각종 네이밍이나 줄 띄움, 기능 모듈화 등 보기 편한 코드를 작성하기 위한 컨벤션들이 이를 실현하기 위한 도구에 해당된다.
◼ Sparse is better than dense 항목도 비슷한 의미를 가진다. 한 줄에 뭉쳐놓은 긴 코드를 작성하기보단, 여러 줄로 나누어 작성하라는 의미이다.
▣ Explicit is better than implicit
함축적인 표현 보다는 명확한 표현을 추구하라는 의미이다. 변수명이나 클래스 이름, 클래스 메소드 이름을 짓는 데에 적용될 수도 있고, 좀 많이 나아간 케이스지만 이전 포스트에서 언급한 object 클래스를 일부러 명시적으로 상속시키는 Python3 클래스 정의의 케이스도 있다. 아마 이 케이스에서 object의 암묵적인 상속이 unPythonic 하다고 주장한 사람들은 이 격언을 떠올린 것일지도 모른다.
프로그래밍은 단순한 기능의 구현 뿐만 아니라 다른 작업자와의 커뮤니케이션을 필요로 하는 작업이기 때문에 뭔가를 암묵적으로 숨겨 놓기보다는 항상 명시적으로 코드를 작성해 놓는 것이 좋다.
◼ Readability counts 와도 연관되는데, 되도록이면 명확하고 읽기 쉽게 이름을 짓고 코드를 작성하라는 격언이다.
▣ Simple is better than complex
최대한 간단한 구현 방법을 택하라는 의미이다. 어떤 언어가 그렇지 않냐 싶겠지만, 파이썬에서 특정한 기능을 구현하는 방식은 여러 가지가 존재한다. 하지만 파이썬이 기본적으로 제공하는 기능을 충분히 이용하지 않고 C언어 등에서 사용할 법한 문법으로 괴상하게 구현하는 방법과, 반대로 기능을 잘 살려 간단명료하게 구현하는 방법이 있다면 당연히 후자를 선택해야 한다.
▣ Complex is better than complicated
하지만 문제 상황 자체가 매우 어려워서 간단한 구현이 어려울 수도 있다. 이런 상황에서는 어거지로 간단한 구현을 하기 위해 여기저기 뒤얽힌 괴상한 코드를 만들어 내기보다는, 차라리 복잡한 문제를 위한 복잡한 구현을 택하라는 이야기이다.
◼ If the implementation is hard to explain, it’s a bad idea / ◼ If the implementation is easy to explain, it may be a good idea 와도 관련이 있는데, 단순히 제 기능을 하는 고성능의 구현을 택하기보단, 다른 작업자가 읽고 이해할 수 있는 구현을 선택하라는 의미이다.
▣ Flat is better than nested
코드를 서브모듈화, 서브클래스화 하는 것은 분명히 어느 수준까지는 더 나은 사용성과 편리함을 제공하지만, 코드를 계속 발전시키는 과정에서 단계를 너무 많이 만들면 오히려 사용성과 편리함은 감소할 수 있다. 따라서 정말 필요한 경우가 아니라면 한 모듈, 클래스 단계 내에서 수평하게 (flat) 코드를 작성해 놓는 것이 좋다는 의미이다.
▣ Special cases aren’t special enough to break the rules... Although practicality beats purity.
이 두 격언은 서로 상반되는 주장을 하고 있다. 한 쪽은 아무리 더 나은 구현을 위해서라도 미리 정해놓은 프로그래밍 규칙은 절대 위반할 수 없다는 입장이고, 다른 한 쪽은 실용성을 위해서라면 가끔씩은 허용이 필요하다는 입장이다. 이 상반되는 두 격언은 규칙 vs 실용성 이슈에 대한 명확한 정답은 없다는 것을 시사하며, 둘 사이에서 적절한 균형점을 찾아야 한다고 이야기 하고 있다.
▣ Errors should never pass silently... Unless explicitly silenced
각종 에러 상황에서 단순 에러 코드나 성공/실패 여부를 나타내는 bool 변수, 혹은 None 을 반환시키는 식으로 조용한 에러 처리를 하기 보다는 명확하게 에러를 raise 해 주는 것이 좋다고 말하고 있다. 프로그램이 내부에서 발생하는 에러 상황을 그대로 안고 길게 실행되어 나중에 에러 발생지점을 찾기 어렵게 만드는 것 보다, 프로그램 실행이 실패할 거라면 일찍, 에러 발생 지점과 최대한 가깝게 에러를 명시적으로 raise 하는 것이 좋다는 뜻이다.
◼ In the face of ambiguity, refuse the temptation to guess 는 에러가 발생하는 상황에서 에러에 대한 원인을 넘겨짚고 때려 맞추는 식으로 해결하기 보다는, 항상 논리적이고 신중한 접근을 통해 문제를 명확하게 해결하라는 격언이다. 넘겨짚는 식으로 해결된 (것 처럼 보이는 문제) 는 이후에 다른 문제를 발생시킬 가능성이 높다.
일부만 짚어보려 했는데 거의 다 본 것 같다 (...).
이 Zen of Python은 PEP 20번으로 Python enhancement proposal에 올라가 있으며, 이전 포스트에서 언급한 PEP 8은 더욱 pythonic 한 코드를 작성하기 위한 규칙을 알려주고 있다.
이 격언들을 통해서 파이썬에서 자체적으로 제공하는 코딩 규칙 (PEP 8), 그리고 파이썬 커뮤니티에서 pythonic 이라 일컬어되는 일종의 프로그래밍 스타일에 대해서 더 잘 이해할 수 있을 것이라 생각한다.
참고로, The Hitchhiker’s Guide to Python 공식 사이트에서도 pythonic한 코드를 작성하는 방법에 대해서 각종 예시와 도움이 되는 도구를 함께 소개해 주고 있으니, 이것도 한번 읽어보는 것을 강력히 추천한다!
이 포스트가 더 나은 파이썬 프로그래밍을 하게 되는 계기가 되었으면 좋겠다.
아래는 참고할 만한 사이트들이다.
References
PEP 20 -- The Zen of Python
https://www.python.org/dev/peps/pep-0020/
PEP 8 -- Style Guide for Python Code (강추!)
https://www.python.org/dev/peps/pep-0008/
The Hitchhiker’s Guide to Python: Code Style (강추!)
https://python-guide-kr.readthedocs.io/ko/latest/writing/style.html
Attributes of Python module `this`
https://stackoverflow.com/questions/37301273/attributes-of-python-module-this
[Python] PEP 8: E722 do not use bare 'except'
[Python] 클래스가 object를 상속받는 경우