Chapter2. Pythonic Code

  • 파이썬 언어의 고유한 관용구
  • 권장사항에 따른 파이썬스러운 코드
  • 일반적으로 더 나은 성능
  • 이해하기 쉽고 전체 개발자가 동일한 패턴과 구조에 익숙해지면 실수를 줄일 수 있음

[프로퍼티, 속성과 객체 메서드의 다른 타입들]

파이썬에서의 밑줄

  • 파이썬 객체의 모든 프로퍼티와 함수는 public
  • 엄격한 강제 사항은 없짐나 몇가지 규칙이 있음
  • 밑줄(한개, _)로 시작하는 속성은 해당 객체에 대해 private을 의미, 외부에서 호출하지 않기를 "기대", 금지는 아님
  • 밑줄 두개 쓰지말기, 두개 쓰면 name mangling 을 하는 것임.  여러 번 확장되는 클래스의 메서드를 이름 충돌 없이 오버라이드 하기 위함. 즉, 속성을 private으로 정의하려는 경우 하나의 밑줄을 사용하는 파이써닉한 관습을 지켜야 함

프로퍼티

  • 객체의 속성에 대한 접근을 제어 할때 사용
  • 자바 같은 다른 언어에선 getter, setter를 사용하지만 파이썬은 프로퍼티 사용

  • 객체의 모든 속성에 대해서 get, se 메서드를 작성할 필요는 없음. 대부분의 경우 일반 속성을 사용. 속성 값을 가져오거나 수정할 때 특별한 로직이 필요한 경우에만 프로퍼티 사용

[이터러블 객체]

  • 기본적으로 반복 가능한 객체, 리스트, 튜플, 세트, 딕셔너리
  • 이터러블 :__iter__ 매직 메서드를 구현한 객체
  • 이터레이터 :__next__ 매직 메서드를 구현한 객체
  • 파이썬은 이터러블 확인을 위해
    • 객체가 __next__ 나 __iter__ 이터레이터 메서드 중 하나를 포함하는지 여부
    • 객체가 시퀀스이고, __len__과 __getitem__를 모두 가졌는지 여부
  • 를 확인함. 즉 시퀀스도 반복을 할 수 있으므로 이터러블 객체를 만드는 방법은 다음 두가지

이터러블 객체 만들기

  • 파이썬은 반복을 위해 해당 객체의 iter()함수를 호출 -> __iter__메서드 존재를 확인, 있으면 실행
  • 아래는 특정 기간 동안 날짜를 하루 간격으로 출력하는 객체 코드

  • 파이썬은 iter() 함소를 호출 -> __iter__ 매직 메서드 호출 -> __iter__는 self를 반환하고 있으므로 객체 자신이 이터러블임을 나타냄 -> 루프의 각 단계에서 마다 자신의 next() 함수를 호출함 -> next()는 __next__ 매직 메서드에게 위임 -> 이 메서드에서 요소를 어떻게 생산하고 하나씩 반환할 것인지 결정 -> 더이상 생산할 것이 없을 경우 파이썬에게 StopIteration 예외를 발생시켜 알림. 즉 for루프가 StopIteration 예외 발생까지 next()를 호출 하는 셈.

시퀀스 만들기

  • iter()함수는 객체에 __iter__가 없으면 __getitem__을 찾고 없으면 TypeError 발생
  • 시퀀스는  __len__과 __getitem__ 을 구현하고 인덱스 0부터 포함된 요소를 한 번에 하나씩 차례로 가져 올 수 있어야 함
  • 앞의 이터러블로 구현하면, 메모리를 적게 사용하는 장점이 있음. 한 번에 하나의 날짜만 보관하고 한 번에 하나씩 날짜를 생성하는 법을 알고 있음. 그러나 n번째 요소를 얻고 싶다면 도달 할 때 까지 n 번 반복해야함. O(n)
  • 시퀀스로 구현하면 모든 것을 한번에 보관해야 해서 더 많은 메모리가 사용되지만 특정 요소를 가져 오기 위한 인덱싱의 시간 복잡도는 O(1)

  • 메모리, CPU 사이 tradeoff를 고려하여 이터러블, 시퀀스 중에 어떤 걸 쓸지 결정. 일반적으론 이터레이션이 더 좋은 선택이고 나중에 나올 제너레이터는 더 바람직한 선택.
  • https://mingrammer.com/translation-iterators-vs-generators/

[컨테이너 객체]

  • __contains__ 메서드를 구현 한 객체
  • in 키워드로 호출되고 Boolean 반환
  • 파이썬은 이렇게 해석 element in container -> container.__contains__(element)
  • 이 메서드를 잘 활용하면 코드의 가독성이 높아지며 파이써닉함
  • https://corikachu.github.io/articles/python/python-magic-method

 

[호출형(callable) 객체]

  • 매직 메서드 __call__을 사용하면 객체를 일반 함수처럼 호출 할 수 있음
  • 여기에 전달된 모든 파라미터는 __call__메서드에 그대로 전달 됨
  • 객체에는 상태가 있기 때문에 함수 호출 사이에 정보를 저장할 수 있다는 이점
  • 파이썬은 obejct(*args, **kwargs)를 object.__call__(*args, **kwargs)로 변환
  • 이 메서드는 객체를 파라미터가 있는 함수처럼 사용하거나 정보를 기억하는 함수처럼 사용할 경우 유용
  • 아래는 파라미터와 동일한 값으로 몇번 호출 되었나 반환하는 객체 __call__ 사용 예

 

[파이썬에서 유의할 점]

변경 가능한 파라미터의 기본 값

  • 변경 가능한 객체를 함수의 기본 인자로 사용하면 안됨

  • 위 함수에서 인수 값은 최초 딱 한번만 메모리에 생성되는데, 함수 본문에서 이 값에 변화를 주고 있음. (pop으로 제거) , 그래서 두번째 호출에서는 값이 없기 때문에 에러가 남. 주석 처리 한 것 처럼 새 인자값을 매번 줘야지만 에러가 안남

  • 인자값을 None으로 주고 함수 본문에서 기본값을 할당해주면 됨. 함수는 자체 스코프와 생명 주기를 가지므로 None이 나타날때 마다 체크해서 기본 값 주면 됨.