-
assert
디버깅 목적으로 표준 코드를 사용하는 대신 표준 코드의 일부로 사용하면 성능 또는 코드 유지 관리 문제가 있습니까?입니다
assert x >= 0, 'x is less than zero'
보다 나은 또는 나쁜
if x < 0: raise Exception, 'x is less than zero'
-
또한 비즈니스 규칙을 설정하는 방법이 있습니까? 그렇지
if x < 0 raise error
않고 항상 확인try/except/finally
하십시오. 코드 전체에서 언제라도x
0보다 작은 경우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
이 네 가지 역할을 :
-
Alice, Bernd, Carl 및 Daphne에게 코드에 필요한 것을 알립니다.
튜플 목록을 처리하는 메소드가 있고 해당 튜플을 변경할 수없는 경우 프로그램 로직이 중단 될 수 있다고 가정하십시오.def mymethod(listOfTuples): assert(all(type(tp)==tuple for tp in listOfTuples))
이는 문서의 동등한 정보보다 신뢰할 수 있으며 유지 관리가 훨씬 쉽습니다.
-
코드에 필요한 것을 컴퓨터에 알리십시오.
assert
코드 발신자로부터 올바른 행동을 취합니다. 코드가 Alices와 Bernd의 코드를 호출하면을 제외하고assert
프로그램이 Alices 코드에서 충돌하는 경우 Bernd는 Alice의 결함이라고 가정하고 Alice는이를 조사하고 결함이라고 가정 할 수 있습니다. 그의. 많은 작업이 손실되었습니다.
어설 션을 사용하면 전화가 잘못 된 사람은 자신의 잘못이 아니라 자신의 잘못이라는 것을 빨리 알 수 있습니다. 앨리스, 베른 그리고 당신은 모두 이익을 얻습니다. 엄청난 시간을 절약합니다. -
어느 시점에서 코드가 달성 한 것을 코드 독자 (자신 포함)에게 알리십시오.
항목 목록이 있고 각 항목이 깨끗하거나 (좋으면) smorsh, trale, gullup 또는 twinkled (모두 허용되지 않음) 일 수 있다고 가정하십시오. 스모 시일 경우 스모시되지 않아야합니다. 그것이 trale라면 그것은 baludoed해야합니다; gullup 인 경우 뛸 수 있어야합니다. 반짝 거리면 목요일을 제외하고 다시 반짝 여야합니다. 당신은 아이디어를 얻는다 : 그것은 복잡한 일이다. 그러나 최종 결과는 모든 항목이 깨끗하다는 것입니다. 올바른 일 (TM)은 세척 루프의 효과를 다음과 같이 요약합니다.assert(all(entry.isClean() for entry in mylist))
이 문장은 훌륭한 루프가 달성하는 것이 무엇인지 정확히 이해하려는 모든 사람들에게 두통을 덜어줍니다 . 그리고이 사람들 중 가장 빈번하게 자신이 될 것입니다.
-
어느 시점에서 코드가 달성 한 것을 컴퓨터에 알리십시오.
뛸 때 필요한 항목을 조정하는 것을 잊어 버린 경우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
코드가 정확하고 단일 이벤트 장애, 하드웨어 오류 등을 제외하면 어떤 주장도 실패하지 않습니다 . 따라서 최종 사용자에 대한 프로그램의 동작이 영향을받지 않아야합니다. 특히 예외적 인 프로그래밍 조건 에서도 어설 션이 실패 할 수 없습니다 . 그것은 결코 일어나지 않습니다. 이 경우 프로그래머가 압축해야합니다.