• Pythonic: 파이썬 헬퍼클래스


    * dict와 tuple보다 class를 사용해야 할 때

    손 쉬운 사용은 코드를 취약하게 한다

    dict는 객체의 수명이 지속되는 동안 예측불가능한 식별자들을 관리하는 용도로 아주 좋다.

    예시 1. 아이템을 드랍하는 몬스터

    예를 들어, 다음 코드를 봐보자. 몬스터 별 드랍되는 아이템을 쉽게 지정하고 그 결과를 볼 수있다.

    import random
    
    class Monsters(object):
        def __init__(self):
            self._list = {}
        def add_monster(self, name):
            self._list[name] = []
        def set_drop(self, name, item):
            self._list[name].append(item)
        def drop(self, name):
            return random.choice(self._list[name])
    
    monsters = Monsters()
    monsters.add_monster('hidekuma')
    monsters.set_drop('hidekuma', 'sword')
    monsters.set_drop('hidekuma', 'shield')
    
    print(monsters.drop('hidekuma'))
    
    >>>
    sword
    


  • Python: asyncio를 더 빠르게 만드는 uvloop 살펴보기


    * uvloop

    uvloop는 asyncio의 이벤트 루프 대체재로, asyncio를 더 빠르게 만들고, nodejs, gevent 및 다른 python 프레임워크와 비교해봐도, 2배이상의 퍼포먼스를 보여준다.

    tip
    python3.5 부터 파이썬 표준 라이브러리에 추가된 asyncio는 비동기 I/O 프레임워크이다.

    asyncio & uvloop

    asnycio는 네트워크 전송, 프로토콜 및 스트림 추상화 컬렉션과 이벤트 루프 기능이 있으며, 이벤트 루프는 asyncio의 핵심이다. asyncio의 주요기능들은 다음과 같다.

    • 스케줄링에 의한 호출
    • 네트워크를 통한 데이터 전송
    • DNS 쿼리수행
    • OS 신호 핸들링
    • 서버와 커넥션을 만드는 편리한 추상화
    • 비동기적 서브프로세스


  • Pythonic: 파이썬의 키워드 전용인수


    * 키워드 전용인수

    파이썬 뿐만아니라 많은 언어에서 우리는 당연한듯 자주 사용하는 부분일 것이다. 키워드 인수를 통해 우리는 함수의 명료성을 강조할 수 있다.

    위치 인수만을 이용한 함수

    def say(msg, delimiter, user):
      print('{user} say {delimiter} {msg}'.format(msg=msg, delimiter=delimiter, user=user))
    
    say('test', ':', 'unknown')
    say('test', ':', 'hidekuma')
    
    >>>
    unknown say : test
    hidekuma say : test
    

    크게 어렵지 않게 이해할 수 있는 코드이다. 문제는 위치인수 모두 str 타입을 받기 때문에, 인수의 위치를 혼동하기 쉽다는 것이다. 이 때문에 함수의 내용이 복잡해지면 복잡해질 수록, 찾기 어려운 버그가 쉽게 발생할 수있다. 해당 코드의 가독성을 높여보자.



  • Pythonic: 파이썬의 가변 위치 인수


    * 가변 위치 인수

    선택적 위치 인수

    관례적으로 *args 혹은 star args라고 한다. 해당 위치 인수를 통해 함수 호출을 명확히 할 수 있다. 다음 예시1을 봐보자. 호출 단에서 몇 가지 문제점이 보여질 것이다.

    예시1

    def printt(inputs):
        prt = 'Nope' 
        if inputs:
            prt = ' '.join(str(x) for x in inputs)
        print(prt)
    
    printt(['args', 'must', 'be', 'included'])
    printt([]) # 굳이 빈 리스트를 넣어줘야 한다.
    printt() # 에러발생.
    
    >>>
    args must be included
    Nope
    TypeError: printt() takes exactly 1 argument (0 given)
    

    해당 코드같은 경우 굳이 프린트 할 데이터가 없다 해도 빈 리스트를 넣어주지 않으면, 마지막처럼 에러가 난다. 해당 코드를 선택적 위치 인수로 이용해보면 다음과 같다.



  • Pythonic: 이터레이터 알아보기


    * 이터레이터의 특별한 특징

    소진성

    제너레이터가 반환한 이터레이터는 호출 되면, StopItreration Exception을 일으킨 후 데이터가 소진된다.

    예시1

    제너레이터를 생성하는 함수이며, 리턴받은 이터레이터를 리스트로 만든다(순회시킨다).

    def generated_data():
        for i in range(10):
            yield i
    result = generated_data()
    
    print(result) # 제너레이터 생성확인
    print(list(result)) # 제너레이터 첫번째 순회 - 이터레이터 순회 (StopIteation)
    
    >>>
    <generator object generated_data at 0x102402be0>
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    

    여기서 한번 더 호출해본다.

    print(list(result)) # 제너레이터의 두번째 순회 - 이터레이터 이미 소진
    
    >>>
    [] # 빈 list
    

    제너레이터의 반환 값에 아무런 결과도 생성되지 않는다. 이런 특징을 일회성(소진성)이라고 한다. 이러한 소진성을 해결하기 위해서는 제너레이터에서 반환한 이터레이터를 새로운 변수에 할당하여, 복사해야한다.