본문 바로가기
TechBooks

[Python] 파이썬 코딩의 기술 1장

by 꿈나무 김땡땡 2022. 3. 6.

1장 파이썬답게 생각하기

  • 파이썬 프로그래머는 명시적인 것을 좋아하고, 복잡한 것보다 단순한 것을 좋아하며, 가독성을 최대한 높이려고 노력한다.

The Zen of Python

  • 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! 네임스페이스는 정말 대단한 아이디어다. -- 자주 사용하자!

출처: https://wikidocs.net/7907

 

0.2 파이썬의 선 (The Zen of Python)

파이썬 다운 코딩은 어떤 것일까? 언어에는 그에 맞는 적절한 표현 방식이 있다. 외국인이 우리말을 할 때, 문법적으로는 틀리지 않았다고 해도 듣기에 영 어색한 경우가 있다 ...

wikidocs.net

 

Better Way 1. 사용 중인 파이썬의 버전을 알아두라

  • $python --version 또는 $python3 --version 으로 버전 확인 가능
  • 또는 아래 코드로 확인 가능
import sys
print(sys.version_info)
print(sys.version)

 

Better Way 2. PEP 8 스타일 가이드를 따르라

  • PEP 8 : Python Enhancement Proposal #8. 파이썬 코드를 어떤 형식으로 작성할지 알려주는 스타일 가이드
  • https://wikidocs.net/7896 에서 한글 번역본 확인 가능

 

Better Way 3. bytes와 str의 차이를 알아두라

  • bytes / str는 호환 되지 않는다.
  • + 연산자를 사용해 bytes끼리 / str끼리 합칠 수 있다. (bytes+str는 불가)
print(b'one'+b'two') // b'onetwo'
print('one'+'two') //'onetwo'
  • 이항 연산자를 사용해 bytes끼리 / str끼리 비교할 수 있다. (bytes & str 간에는 불가)
assert b'red' > b'blue'
assert 'red' > 'blue'
  • 참고
    • assert문: assert는 뒤의 조건이 True가 아니면 AssertError를 발생 시킨다. 예를 들어 반드시 int만 써야 할 경우 제한 가능
    • 가정 설정문(assert) : https://wikidocs.net/21050
 

03_가정 설정문(assert)

assert는 뒤의 조건이 True가 아니면 AssertError를 발생한다. ``` >>> a = 3 >>> assert a == 2 #결과 Traceback (mos ...

wikidocs.net

lists = [1, 3, 6, 3, 8, 7, 13, 23, 13, 2, 3.14, 2, 3, 7]

def test(t):
    assert type(t) is int, '정수 아닌 값이 있네'

for i in lists:
    test(i)
    
# result) AssertionError: 정수 아닌 값이 있네

 

  • 파일을 읽을 때도 bytes는 with open('data.bin', 'wb')로 / str는 with open('data.bin', 'w')로 열어야 한다.

 

Better Way 4. C 스타일 형식 문자열을 str.format과 쓰기 보다는 f-문자열을 통한 인터폴레이션을 사용하라

  • f-문자열 사용을 권장
key = 'my_var'
value = 1.234

formatted = f'{key} = {value}'
print(formatted) # my_var = 1.234
  • f-문자열 안에서 값을 유니코드나 repr 문자열로 변환하는 기능도 사용 가능
formatted = f'{key!r:<10} = {valuse:.2f}'
print(formatted) # 'my_var' = 1.23
  • f-문자열 안에서 출력할 숫자 개수를 변수로 받을 수도 있다.
places = 3
number = 1.23456

print(f'내가 고른 숫자는 {number:.{places}f}') # 내가 고른 숫자는 1.235

 

Better Way 5. 복잡한 식을 쓰는 대신 도우미 함수를 작성하라

  • boolean 연산자 or나 and를 식에 사용하는 것보다 if/ else 식을 쓰는 편이 더 가독성이 좋다.
  • 파라미터가 없거나 비어 있을 경우 0이 디폴트 값으로 대입 되도록 하는 함수를 작성하는 예시
  • 방법1 : 읽기 너무 어렵고 시각적 잡음이 많다. 코드를 새로 읽는 사람이 이 식이 실제로 어떤 일을 하는지 이해하기 위해 너무 많은 시간을 투자해야 한다. 코드를 짧게 유지하면 멋지기는 하지만, 모든 내용을 한 줄에 우겨 넣기 위해 노력할 만큼의 가치는 없다.
# 질의 문자열이 '빨강=5&파랑=0&초록'인 경우
red = my_values.get('빨강', [''])[0] or 0
green = my_values.get('초록', [''])[0] or 0
opacity = my_values.get('투명도', [''])[0] or 0

print(f'빨강: {red!r}') # 빨강: '5'
print(f'초록: {green!r}') # 파랑: 0
print(f'투명도: {opacity!r}') # 투명도: 0
  • 방법2: 방법 1보다 명확하지만 완전한 if/ else 문 보다는 덜 명확하다.
red_str = my_values.get('빨강', [''])
red = int(red_str[0]) if red_str[0] else 0
  • 방법3: 완전한 if/ else문
green_str = my_values.get('초록', [''])
if green_str[0]:
	green = int(green_str[0])
else:
	green = 0
  • 방법3을 반복 적용하려면 (이 예제처럼 2-3번에 불과할지라도) 꼭 도우미 함수를 작성해야 한다.
def get_first_int(values, key, default=0):
	found = values.get(key, [''])
    if found[0]:
    	return int(found[0])
    return default

green = get_first_int(my_values, '초록')
  • 도우미 함수 호출 코드를 사용해 작성한 코드는 매우 명확함 !
  • 식이 복잡해지기 시작하면 바로 식을 더 작은 조각으로 나눠서 로직을 도우미 함수로 옮길지 고려할 것
  • 아무리 짧게 줄여 쓰는 것을 좋아한다 해도, 코드를 줄여 쓰는 것보다 가독성을 좋게 하는 것이 더 가치 있다

 

Better Way 6. 인덱스를 사용하는 대신 대입을 사용해 데이터를 언패킹하라

  • 파이썬에서도 JS의 할당 방법 사용 가능!
  • index 대신 unpacking 사용
  • 모든 Iteration 구문에 사용 가능
  • 언패킹(unpacking) 구문 : 한 문장 안에서 여러 값을 대입할 수 있다.
item = ('호박엿', '식혜')
first, second = item # unpacking
print(first, '&', second) # 호박엿 & 식혜

 

  • list iteration 을 할 때도 index 보다 unpacking 사용을 추천
snacks = [('베이컨', 350), ('도넛', 240), ('머핀', 190)]

# 방법1: list iteration
for i in range(len(snacks)):
	item = snacks[i]
    name = item[0]
    calories = item[1]
    print(f'#{i+1}: {name} 은 {calories}kcal 입니다')
    # #1: 베이컨 은 350kcal 입니다
    
# 방법2: unpacking (권장)
for rank, (name, calories) in enumerate(snacks, 1):
	print(f'#{rank}: {name} 은 {calories}kcal 입니다')
    # #1: 베이컨 은 350kcal 입니다

 

댓글