본문 바로가기
파이썬

effective pyton 을 읽고

by 혜룐 2016. 5. 16.



effective pyton 을 읽고


  • 제너레이터 표현식은 이터레이터로 한번에 한 출력만 만드므로 메모리문제를 피할수있다.
  • range 보다는 enumerate(lazy generator 로 이터레이터를 감싼다.)  를 사용하자.
    • 이터레이터를 병렬로 처리 하려면 zip을 쓴다. (길이가 다른 경우에는 itertolls의 izip_longest)
  • for / while 루프 뒤에는 else 블럭을 쓰지말자.
  • try/exception/else/finally  에서 각 블럭의 장점을 이용하자.
    • else블럭 : try 블럭이 예외를 일으키지않으면 else블럭이 실행된다. 즉 try블럭의 코드가 성공적으로 실행된 후, finally 블럭에서 공통처리 코드를 실행하기 전에 사용하면 좋다. 또한 이 블럭은 try/exception 블럭과 성공한 경우에 실행할 코드를 시각적으로 구분해준다.
  • 함수에 None 을 반환하기 보다는 예외를 일으키자.
    • 함수를 만들때 넌을 반환하지 않도록 해 오류를 줄이는게 좋다. 호출하는 쪽에 예외를 일으켜 그 예외처리를 하게 하는 것이 좋다. 이유는 None을 반환하게 되면, 조건식에서 False로 평가되기 때문이다.
  • 키워드전용인수
    • 3에서는 함수의 키워드 전용 인수 문법을 명시적으로 지원한다.
    • 2에서는  **kwargs 를 사용하고, TypeError 예외를발생시켜, 함수의 키워드 전용 인수를 흉내낼수있다. 
# -*- coding: utf-8 -*-
import os
from unittest import TestCase


class TestEffective(TestCase):
'''

'''
def test_keyword_only(self):
res = self.test_safe_division_c(12,4)
self.assertEqual(res, 3)

res1 = self.test_safe_division_c(12,0, ignore_zero_division=True)
self.assertEqual(res1, float('inf') )

res2 = self.test_safe_division_c(12,3, ignore_overflow=True)
self.assertEqual(res2, 4)

def test_safe_division_c(self, num , divisor, **kwargs):
ignore_overflow= kwargs.pop("ignore_overflow", {})
ignore_zero_division= kwargs.pop("ignore_zero_division", {})

if kwargs:
raise TypeError("Unexpected **kwargs: %r" % kwargs)

try:
return num/divisor
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_division:
return float('inf')
else:
raise

  • 튜플을 길게 확장하는 패턴은 클래스의 계층을 나눠라.
    • 파이썬에서는 관례적으로 사용하지 않을 변수에 _ 밑줄 변수 이름을 쓴다.
  • 인터페이스가 간단하면 클래스 대신 함수를 받자.
  • __call__  메서드는 클래스의 인스턴스를 일반 파이썬 함수처럼 호출할수 있게 해준다.
    • 상태를 보전하는 함수가 필요할때, 상태 보존 클로저를 정의하는 대신 __call__ 메서드를 제공하는 클래스를 정의하는 방안을 고려하자.
  • 인스턴스 수준에서 동작을 교체할수 있게 만들어서 믹스인 클래스가 요구할때 클래스별로 원하는 동작을 하게 하자.
  • 메타클래스와 속성
    • 메타클래스를 이용하면 파이썬의 class문을 가로채서 클래스가 정의될때마다 원하는 동작을 제공할수있다. = 속성을 설정할때 @property  데코레이터와 @setter 으로 속성을 바꿀수있다. 
    • 객체의 속성에 접근할때 특별한 동작을 재정의 하는 방법으로 사용할수있다. property 를 사용해 더 나은 모델을 만드는 리팩토링 과정으로 쓰면 좋겠다.
    • 또는 검증코드로 사용할수도 있다.
class Homework(object):
def __init__(self):
self._grade = 0

@property
def grade(self):
return self._grade

@grade.setter
def grade(self, value):
if not (0 <= value <= 100):
raise ValueError("must be between 0 and 100")
self._grade = value


class TestEffective(TestCase):

def test_t_property(self):
h = Homework()
h.grade = 200
    • 간단한 public속성을 사용해, 새 클래스의 인터페이스를 정의하는게 > 세터와 게터메서드를 만드는 것 보다 좋다.
  • __getattr__ : lazy
    • 클래스에 __getattr__ 메스드를 정의하면 객체의 인스턴스 딕셔너리에서 속성을 찾을수없을때 이 메서드가 한번 호출된다.
    • 존재하지 않는 속성에 접근하면  __getattr__ 메서드를 호출하게 되고, 이어서 인스턴스 딕셔너리 __dict__를 변경하게 된다.
    • 보통 attr이 없으면 has no attr  뱉는다. (아래 주석부분을 없애고 코드를 다시 돌리게 되면 __getattr__메서드를 호출하게 되고, 인스턴스의 __dict__ 을 변경하게 되는걸 볼수 있다.)

class MongoDBSchemaless(object):
def __init__(self):
self.exist = 5

'''
없는 속성을 접근했을때, 파이썬에서는 __getattr__ 메서드를 찾는다.

def __getattr__(self, name ):
value = None
setattr(self, name, value)
return value

'''


class TestEffective(TestCase):

def test__how_to_getattr(self):
data = MongoDBSchemaless()
print("before:", data.__dict__)
print("after:", data.new_attr_test)

if data.new_attr_test:
print("val is None")
else:
print("default val is None")

  • 재사용이 가능한  try/finally 동작을 만들려면  contextlib 와 with문을 고려하자.
    • context manager는 with 문으로 사용할 수 있다.
    •  __enter__() 함수는 with 문 안의 코드가 실행될 때 실행되는 함수이며, __exit__()함수는 with 문 안의 모든 코드가 실행되고 관련된 모든 자원과 메모리가 해제 되는 시점에 실행 된다.
    • contextmanager  로 구현할수있다.
  • 지역시간은 time이 아닌 datetime()을 써야한다.
    • time() : UTC 와 서버 지역시간을 변환하는 목적으로만 사용한다.
    • datetime() :  한 지역시간을 다른 지역시간으로 신뢰성있게 변경한다.pytz 모듈사용하면됨