[python] Python assert 모범 사례

  1. assert디버깅 목적으로 표준 코드를 사용하는 대신 표준 코드의 일부로 사용하면 성능 또는 코드 유지 관리 문제가 있습니까?

    입니다

    assert x >= 0, 'x is less than zero'

    보다 나은 또는 나쁜

    if x < 0:
        raise Exception, 'x is less than zero'
  2. 또한 비즈니스 규칙을 설정하는 방법이 있습니까? 그렇지 if x < 0 raise error않고 항상 확인 try/except/finally하십시오. 코드 전체에서 언제라도 x0보다 작은 경우 assert x < 0함수의 시작 부분에서 함수의 어디에서나 설정하는 것처럼 오류가 발생 합니다 x예외가 발생한 곳 이 0보다 작은 곳 은 어디 입니까?



답변

함수 전체에서 x가 0보다 작을 때 오류를 자동으로 발생시킬 수 있습니다. 클래스 디스크립터 를 사용할 수 있습니다 . 예를 들면 다음과 같습니다.

class LessThanZeroException(Exception):
    pass

class variable(object):
    def __init__(self, value=0):
        self.__x = value

    def __set__(self, obj, value):
        if value < 0:
            raise LessThanZeroException('x is less than zero')

        self.__x  = value

    def __get__(self, obj, objType):
        return self.__x

class MyClass(object):
    x = variable()

>>> m = MyClass()
>>> m.x = 10
>>> m.x -= 20
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "my.py", line 7, in __set__
    raise LessThanZeroException('x is less than zero')
LessThanZeroException: x is less than zero


답변

어설 션은 절대 발생하지 않아야하는 조건을 테스트하는 데 사용해야합니다 . 프로그램 상태가 손상된 경우 일찍 충돌하는 것이 목적입니다.

발생할 수있는 오류에 대해서는 예외를 사용해야하며 거의 항상 자체 예외 클래스를 작성해야합니다 .


예를 들어, 구성 파일 dict에서을 ( 를) 읽는 기능을 작성하는 경우 파일의 형식이 잘못 지정되면을 발생시켜야 ConfigurationSyntaxError하지만 assert을 반환 할 수는 없습니다 None.


예를 들어, x사용자 인터페이스 또는 외부 소스를 통해 설정된 값인 경우 예외가 가장 좋습니다.

x동일한 프로그램에서 자신의 코드로만 설정된 경우 어설 션을 사용하십시오.


답변

컴파일이 최적화되면 “assert”문이 제거됩니다 . 따라서 성능과 기능상의 차이가 있습니다.

컴파일시 최적화가 요청 될 때 현재 코드 생성기는 어설 션 명령문에 대한 코드를 생성하지 않습니다. – 파이썬 2 문서 파이썬 3 문서

당신이 사용하는 경우 assert응용 프로그램 기능을 구현 데 하고 프로덕션 환경에 맞게 배포를 최적화하는 경우 “but-it-it-works-in-dev”결함이 발생합니다.

PYTHONOPTIMIZE-O -OO 참조


답변

네 가지 목적 assert

4 명의 동료 Alice, Bernd, Carl 및 Daphne과 함께 200,000 줄의 코드를 작업한다고 가정합니다. 그들은 당신의 코드를 호출하고, 당신은 그들의 코드를 호출합니다.

그리고 assert네 가지 역할을 :

  1. Alice, Bernd, Carl 및 Daphne에게 코드에 필요한 것을 알립니다.
    튜플 목록을 처리하는 메소드가 있고 해당 튜플을 변경할 수없는 경우 프로그램 로직이 중단 될 수 있다고 가정하십시오.

    def mymethod(listOfTuples):
        assert(all(type(tp)==tuple for tp in listOfTuples))

    이는 문서의 동등한 정보보다 신뢰할 수 있으며 유지 관리가 훨씬 쉽습니다.

  2. 코드에 필요한 것을 컴퓨터에 알리십시오.
    assert코드 발신자로부터 올바른 행동을 취합니다. 코드가 Alices와 Bernd의 코드를 호출하면을 제외하고 assert프로그램이 Alices 코드에서 충돌하는 경우 Bernd는 Alice의 결함이라고 가정하고 Alice는이를 조사하고 결함이라고 가정 할 수 있습니다. 그의. 많은 작업이 손실되었습니다.
    어설 션을 사용하면 전화가 잘못 된 사람은 자신의 잘못이 아니라 자신의 잘못이라는 것을 빨리 알 수 있습니다. 앨리스, 베른 그리고 당신은 모두 이익을 얻습니다. 엄청난 시간을 절약합니다.

  3. 어느 시점에서 코드가 달성 한 것을 코드 독자 (자신 포함)에게 알리십시오.
    항목 목록이 있고 각 항목이 깨끗하거나 (좋으면) smorsh, trale, gullup 또는 twinkled (모두 허용되지 않음) 일 수 있다고 가정하십시오. 스모 시일 경우 스모시되지 않아야합니다. 그것이 trale라면 그것은 baludoed해야합니다; gullup 인 경우 뛸 수 있어야합니다. 반짝 거리면 목요일을 제외하고 다시 반짝 여야합니다. 당신은 아이디어를 얻는다 : 그것은 복잡한 일이다. 그러나 최종 결과는 모든 항목이 깨끗하다는 것입니다. 올바른 일 (TM)은 세척 루프의 효과를 다음과 같이 요약합니다.

    assert(all(entry.isClean() for entry in mylist))

    이 문장은 훌륭한 루프가 달성하는 것이 무엇인지 정확히 이해하려는 모든 사람들에게 두통을 덜어줍니다 . 그리고이 사람들 중 가장 빈번하게 자신이 될 것입니다.

  4. 어느 시점에서 코드가 달성 한 것을 컴퓨터에 알리십시오.
    뛸 때 필요한 항목을 조정하는 것을 잊어 버린 경우 assert하루를 절약하고 Daphne의 코드가 훨씬 나중에 손상되지 않도록하십시오.

내 생각에, assert문서 (1과 3)와 보호 (2와 4)의 두 가지 목적은 똑같이 가치가 있습니다.
사람들에게 알리는 것이 컴퓨터를 알리는 것보다 가치가있을 수 있습니다. 컴퓨터가 의도하는 실수 assert(1 번 경우)와 그 이후의 많은 실수를 막을 수 있기 때문 입니다.


답변

다른 답변 외에도 AssertionErrors 만 예외를 throw한다고 주장합니다. 공리주의 적 관점에서, 어설 션은 어떤 예외를 포착 할 것인지에 대한 세밀한 제어가 필요할 때 적합하지 않습니다.


답변

이 접근 방식에서 실제로 잘못된 유일한 것은 assert 문을 사용하여 매우 설명적인 예외를 만들기가 어렵다는 것입니다. 더 간단한 구문을 찾고 있다면 다음과 같이 수도 있습니다 .

class XLessThanZeroException(Exception):
    pass

def CheckX(x):
    if x < 0:
        raise XLessThanZeroException()

def foo(x):
    CheckX(x)
    #do stuff here

또 다른 문제점은 정상적인 조건 검사에 assert를 사용하면 -O 플래그를 사용하여 디버깅 assert를 비활성화하기가 어렵다는 것입니다.


답변

여기에 주장 된 영어 단어 는 맹세 , 긍정 , avow 의 의미로 사용됩니다 . “check” 또는 “should be”를 의미하지는 않습니다 . 그것은 당신 이 코더로서 맹세 한 진술 을하고 있음을 의미합니다 :

# I solemnly swear that here I will tell the truth, the whole truth, 
# and nothing but the truth, under pains and penalties of perjury, so help me FSM
assert answer == 42

코드가 정확하고 단일 이벤트 장애, 하드웨어 오류 등을 제외하면 어떤 주장도 실패하지 않습니다 . 따라서 최종 사용자에 대한 프로그램의 동작이 영향을받지 않아야합니다. 특히 예외적 인 프로그래밍 조건 에서도 어설 션이 실패 할 수 없습니다 . 그것은 결코 일어나지 않습니다. 이 경우 프로그래머가 압축해야합니다.