问题:Python中“ assert”的用法是什么?
我一直在阅读一些源代码,并且在几个地方看到了的用法assert
。
到底是什么意思?它的用途是什么?
I have been reading some source code and in several places I have seen the usage of assert
.
What does it mean exactly? What is its usage?
回答 0
该assert
语句几乎存在于每种编程语言中。它有助于在程序中尽早发现问题,找出原因,而不是在其他操作后再发现问题。
当你做…
assert condition
…您要告诉程序测试该条件,如果条件为假,则立即触发错误。
在Python中,它大致等于:
if not condition:
raise AssertionError()
在Python Shell中尝试:
>>> assert True # nothing happens
>>> assert False
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
断言可以包括可选消息,您可以在运行解释器时将其禁用。
要在断言失败时打印消息:
assert False, "Oh no! This assertion failed!"
千万不能使用括号调用assert
的功能等。这是一个声明。如果你这样做assert(condition, message)
你会运行assert
一个(condition, message)
元组的第一个参数。
至于禁用它们,运行时,python
在优化模式,其中__debug__
是False
,断言语句将被忽略。只要通过-O
标志:
python -O script.py
有关相关文档,请参见此处。
The assert
statement exists in almost every programming language. It helps detect problems early in your program, where the cause is clear, rather than later as a side-effect of some other operation.
When you do…
assert condition
… you’re telling the program to test that condition, and immediately trigger an error if the condition is false.
In Python, it’s roughly equivalent to this:
if not condition:
raise AssertionError()
Try it in the Python shell:
>>> assert True # nothing happens
>>> assert False
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
Assertions can include an optional message, and you can disable them when running the interpreter.
To print a message if the assertion fails:
assert False, "Oh no! This assertion failed!"
Do not use parenthesis to call assert
like a function. It is a statement. If you do assert(condition, message)
you’ll be running the assert
with a (condition, message)
tuple as first parameter.
As for disabling them, when running python
in optimized mode, where __debug__
is False
, assert statements will be ignored. Just pass the -O
flag:
python -O script.py
See here for the relevant documentation.
回答 1
注意括号。正如上面指出的那样,,因此与类似print(..)
,可以将其外推到assert(..)
,raise(..)
但不应该外推。
这很重要,因为:
assert(2 + 2 == 5, "Houston we've got a problem")
不起作用,不像
assert 2 + 2 == 5, "Houston we've got a problem"
第一个不起作用的原因是bool( (False, "Houston we've got a problem") )
评估为True
。
在语句中assert(False)
,这些只是多余的括号False
,对它们的内容进行求值。但是assert(False,)
现在带括号的是一个元组,非空元组的计算结果为True
布尔值。
Watch out for the parentheses. As has been pointed out above, , so by analogy with print(..)
, one may extrapolate the same to assert(..)
or raise(..)
but you shouldn’t.
This is important because:
assert(2 + 2 == 5, "Houston we've got a problem")
won’t work, unlike
assert 2 + 2 == 5, "Houston we've got a problem"
The reason the first one will not work is that bool( (False, "Houston we've got a problem") )
evaluates to True
.
In the statement assert(False)
, these are just redundant parentheses around False
, which evaluate to their contents. But with assert(False,)
the parentheses are now a tuple, and a non-empty tuple evaluates to True
in a boolean context.
回答 2
正如其他答案所指出的,assert
类似于在给定条件不成立时引发异常。一个重要的区别是,如果使用优化选项编译代码,则assert语句将被忽略-O
。该文档说,assert expression
可以更好地描述为等同于
if __debug__:
if not expression: raise AssertionError
如果您要彻底测试代码,然后在满意所有断言都不失败的情况下发布优化版本,这将非常有用-当优化打开时,__debug__
变量变为False且条件将不再被求值。如果您依靠断言并且没有意识到它们已经消失,那么此功能还可以吸引您。
As other answers have noted, assert
is similar to throwing an exception if a given condition isn’t true. An important difference is that assert statements get ignored if you compile your code with the optimization option -O
. The documentation says that assert expression
can better be described as being equivalent to
if __debug__:
if not expression: raise AssertionError
This can be useful if you want to thoroughly test your code, then release an optimized version when you’re happy that none of your assertion cases fail – when optimization is on, the __debug__
variable becomes False and the conditions will stop getting evaluated. This feature can also catch you out if you’re relying on the asserts and don’t realize they’ve disappeared.
回答 3
Python中断言的目的是通知开发人员程序中不可恢复的错误。
断言并不旨在表示预期的错误情况,例如“找不到文件”,用户可以在其中采取纠正措施(或只是再试一次)。
另一种看待它的方式是说断言是代码中的内部自检。它们通过在代码中声明某些条件是不可能的来工作的。如果不满足这些条件,则意味着程序中存在错误。
如果您的程序没有错误,则这些情况将永远不会发生。但是,如果确实发生了其中一种情况,则程序将因声明错误而崩溃,并确切地告诉您触发了哪个“不可能”条件。这使查找和修复程序中的错误变得更加容易。
这是我写的有关Python断言的教程的摘要:
Python的assert语句是一种调试辅助工具,而不是用于处理运行时错误的机制。使用断言的目的是让开发人员更快地找到错误的可能根本原因。除非程序中存在错误,否则永远不会引发断言错误。
The goal of an assertion in Python is to inform developers about unrecoverable errors in a program.
Assertions are not intended to signal expected error conditions, like “file not found”, where a user can take corrective action (or just try again).
Another way to look at it is to say that assertions are internal self-checks in your code. They work by declaring some conditions as impossible in your code. If these conditions don’t hold that means there’s a bug in the program.
If your program is bug-free, these conditions will never occur. But if one of them does occur the program will crash with an assertion error telling you exactly which “impossible” condition was triggered. This makes it much easier to track down and fix bugs in your programs.
Here’s a summary from a tutorial on Python’s assertions I wrote:
Python’s assert statement is a debugging aid, not a mechanism for handling run-time errors. The goal of using assertions is to let developers find the likely root cause of a bug more quickly. An assertion error should never be raised unless there’s a bug in your program.
回答 4
其他人已经为您提供了指向文档的链接。
您可以在交互式外壳中尝试以下操作:
>>> assert 5 > 2
>>> assert 2 > 5
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
builtins.AssertionError:
第一条语句什么也不做,而第二条语句引发异常。这是第一个提示:断言对于检查在代码的给定位置应为真的条件(通常是函数的开始(前提)和结束(条件))很有用。
断言实际上与合同编程高度相关,这是非常有用的工程实践:
http://en.wikipedia.org/wiki/Design_by_contract。
Others have already given you links to documentation.
You can try the following in a interactive shell:
>>> assert 5 > 2
>>> assert 2 > 5
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
builtins.AssertionError:
The first statement does nothing, while the second raises an exception. This is the first hint: asserts are useful to check conditions that should be true in a given position of your code (usually, the beginning (preconditions) and the end of a function (postconditions)).
Asserts are actually highly tied to programming by contract, which is a very useful engineering practice:
http://en.wikipedia.org/wiki/Design_by_contract.
回答 5
回答 6
assert语句有两种形式。
简单形式assert <expression>
相当于
if __debug__:
if not <expression>: raise AssertionError
扩展形式assert <expression1>, <expression2>
相当于
if __debug__:
if not <expression1>: raise AssertionError, <expression2>
The assert statement has two forms.
The simple form, assert <expression>
, is equivalent to
if __debug__:
if not <expression>: raise AssertionError
The extended form, assert <expression1>, <expression2>
, is equivalent to
if __debug__:
if not <expression1>: raise AssertionError, <expression2>
回答 7
断言是检查程序内部状态是否符合程序员预期的一种系统方法,目的是捕获错误。请参见下面的示例。
>>> number = input('Enter a positive number:')
Enter a positive number:-1
>>> assert (number > 0), 'Only positive numbers are allowed!'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: Only positive numbers are allowed!
>>>
Assertions are a systematic way to check that the internal state of a program is as the programmer expected, with the goal of catching bugs. See the example below.
>>> number = input('Enter a positive number:')
Enter a positive number:-1
>>> assert (number > 0), 'Only positive numbers are allowed!'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: Only positive numbers are allowed!
>>>
回答 8
这是一个简单的示例,将其保存在文件中(假设为b.py)
def chkassert(num):
assert type(num) == int
chkassert('a')
结果是什么时候 $python b.py
Traceback (most recent call last):
File "b.py", line 5, in <module>
chkassert('a')
File "b.py", line 2, in chkassert
assert type(num) == int
AssertionError
Here is a simple example, save this in file (let’s say b.py)
def chkassert(num):
assert type(num) == int
chkassert('a')
and the result when $python b.py
Traceback (most recent call last):
File "b.py", line 5, in <module>
chkassert('a')
File "b.py", line 2, in chkassert
assert type(num) == int
AssertionError
回答 9
如果assert后的语句为true,则程序继续;但是,如果assert后的语句为false,则程序给出错误。就那么简单。
例如:
assert 1>0 #normal execution
assert 0>1 #Traceback (most recent call last):
#File "<pyshell#11>", line 1, in <module>
#assert 0>1
#AssertionError
if the statement after assert is true then the program continues , but if the statement after assert is false then the program gives an error. Simple as that.
e.g.:
assert 1>0 #normal execution
assert 0>1 #Traceback (most recent call last):
#File "<pyshell#11>", line 1, in <module>
#assert 0>1
#AssertionError
回答 10
该assert
语句几乎存在于每种编程语言中。它有助于在程序中尽早发现问题,找出原因,而不是在其他操作后再发现问题。他们总是期待一个True
条件。
当您执行以下操作时:
assert condition
您要告诉程序测试该条件并在错误的情况下立即触发错误。
在Python中,assert
expression等效于:
if __debug__:
if not <expression>: raise AssertionError
您可以使用扩展表达式来传递可选消息:
if __debug__:
if not (expression_1): raise AssertionError(expression_2)
在Python解释器中尝试一下:
>>> assert True # Nothing happens because the condition returns a True value.
>>> assert False # A traceback is triggered because this evaluation did not yield an expected value.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
在主要针对那些认为在assert
和if
语句之间切换的人使用它们之前,有一些注意事项。使用的目的assert
是在程序验证条件并返回应立即停止程序的值的情况下,而不是采取某些替代方法来绕过错误:
1.括号
您可能已经注意到,该assert
语句使用两个条件。因此,千万不能使用括号englobe他们作为一个显而易见的建议。如果您这样做:
assert (condition, message)
例:
>>> assert (1==2, 1==1)
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
您将以代表元组的第一个参数运行assert
带有的a (condition, message)
,这是因为Python中的非空元组始终为True
。但是,您可以单独进行而不会出现问题:
assert (condition), "message"
例:
>>> assert (1==2), ("This condition returns a %s value.") % "False"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: This condition returns a False value.
2.调试目的
如果您想知道何时使用assert
语句。举一个在现实生活中使用的例子:
*当您的程序倾向于控制用户输入的每个参数或其他任何参数时:
def loremipsum(**kwargs):
kwargs.pop('bar') # return 0 if "bar" isn't in parameter
kwargs.setdefault('foo', type(self)) # returns `type(self)` value by default
assert (len(kwargs) == 0), "unrecognized parameter passed in %s" % ', '.join(kwargs.keys())
*数学上的另一种情况是某个方程式的系数或常数为0或非正数:
def discount(item, percent):
price = int(item['price'] * (1.0 - percent))
print(price)
assert (0 <= price <= item['price']),\
"Discounted prices cannot be lower than 0 "\
"and they cannot be higher than the original price."
return price
*甚至是布尔实现的简单示例:
def true(a, b):
assert (a == b), "False"
return 1
def false(a, b):
assert (a != b), "True"
return 0
3.数据处理或数据验证
最重要的是不要依赖该assert
语句执行数据处理或数据验证,因为可以在Python初始化时使用-O
或-OO
标志(分别表示值1、2和0(默认值)或PYTHONOPTIMIZE
环境变量)关闭此语句。。
值1:
*断言被禁用;
*使用扩展名而不是.pyc
; 生成字节码文件;
* sys.flags.optimize
设置为1(True
);
*和,__debug__
设置为False
;
值2:再禁用一件事
*文档字符串被禁用;
因此,使用该assert
语句来验证某种预期数据非常危险,这甚至暗示了某些安全问题。然后,如果您需要验证某些权限,我建议您raise AuthError
代替。作为先决条件,assert
程序员通常在没有用户直接交互的库或模块上使用an 。
The assert
statement exists in almost every programming language. It helps detect problems early in your program, where the cause is clear, rather than later as a side-effect of some other operation. They always expect a True
condition.
When you do something like:
assert condition
You’re telling the program to test that condition and immediately trigger an error if it is false.
In Python, assert
expression, is equivalent to:
if __debug__:
if not <expression>: raise AssertionError
You can use the extended expression to pass an optional message:
if __debug__:
if not (expression_1): raise AssertionError(expression_2)
Try it in the Python interpreter:
>>> assert True # Nothing happens because the condition returns a True value.
>>> assert False # A traceback is triggered because this evaluation did not yield an expected value.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
There are some caveats to seen before using them mainly for those who deem to toggles between the assert
and if
statements. The aim to use assert
is on occasions when the program verifies a condition and return a value that should stop the program immediately instead of taking some alternative way to bypass the error:
1. Parentheses
As you may have noticed, the assert
statement uses two conditions. Hence, do not use parentheses to englobe them as one for obvious advice. If you do such as:
assert (condition, message)
Example:
>>> assert (1==2, 1==1)
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
You will be running the assert
with a (condition, message)
which represents a tuple as the first parameter, and this happens cause non-empty tuple in Python is always True
. However, you can do separately without problem:
assert (condition), "message"
Example:
>>> assert (1==2), ("This condition returns a %s value.") % "False"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: This condition returns a False value.
2. Debug purpose
If you are wondering regarding when use assert
statement. Take an example used in real life:
* When your program tends to control each parameter entered by the user or whatever else:
def loremipsum(**kwargs):
kwargs.pop('bar') # return 0 if "bar" isn't in parameter
kwargs.setdefault('foo', type(self)) # returns `type(self)` value by default
assert (len(kwargs) == 0), "unrecognized parameter passed in %s" % ', '.join(kwargs.keys())
* Another case is on math when 0 or non-positive as a coefficient or constant on a certain equation:
def discount(item, percent):
price = int(item['price'] * (1.0 - percent))
print(price)
assert (0 <= price <= item['price']),\
"Discounted prices cannot be lower than 0 "\
"and they cannot be higher than the original price."
return price
* or even a simple example of a boolean implementation:
def true(a, b):
assert (a == b), "False"
return 1
def false(a, b):
assert (a != b), "True"
return 0
3. Data processing or data validation
The utmost importance is to not rely on the assert
statement to execute data processing or data validation because this statement can be turned off on the Python initialization with -O
or -OO
flag – meaning value 1, 2, and 0 (as default), respectively – or PYTHONOPTIMIZE
environment variable.
Value 1:
* asserts are disabled;
* bytecode files are generated using extension instead of .pyc
;
* sys.flags.optimize
is set to 1 (True
);
* and, __debug__
is set to False
;
Value 2: disables one more stuff
* docstrings are disabled;
Therefore, using the assert
statement to validate a sort of expected data is extremely dangerous, implying even to some security issues. Then, if you need to validate some permission I recommend you raise AuthError
instead. As a preconditional effective, an assert
is commonly used by programmers on libraries or modules that do not have a user interact directly.
回答 11
正如在C2 Wiki上简要概述的那样:
断言是程序中特定点的布尔表达式,除非程序中存在错误,否则该表达式为真。
您可以使用一条assert
语句来记录您在特定程序点上对代码的理解。例如,您可以记录关于输入(前提条件),程序状态(不变式)或输出(后置条件)的假设或保证。
如果您的断言失败了,这将向您(或您的后继者)发出警报,提醒您在编写程序时对程序的理解是错误的,并且可能包含错误。
有关更多信息,John Regehr在“ Assertions”中有一篇精彩的博客文章,该文章也适用于Python assert
语句。
As summarized concisely on the C2 Wiki:
An assertion is a boolean expression at a specific point in a program which will be true unless there is a bug in the program.
You can use an assert
statement to document your understanding of the code at a particular program point. For example, you can document assumptions or guarantees about inputs (preconditions), program state (invariants), or outputs (postconditions).
Should your assertion ever fail, this is an alert for you (or your successor) that your understanding of the program was wrong when you wrote it, and that it likely contains a bug.
For more information, John Regehr has a wonderful blog post on the Use of Assertions, which applies to the Python assert
statement as well.
回答 12
如果您想确切知道保留函数在python中的作用,请输入 help(enter_keyword)
确保您输入的保留关键字是否作为字符串输入。
If you ever want to know exactly what a reserved function does in python, type in help(enter_keyword)
Make sure if you are entering a reserved keyword that you enter it as a string.
回答 13
Python 断言基本上是一种调试辅助工具,用于测试代码内部自检的条件。当代码陷入不可能的情况时,Assert使调试变得非常容易。断言检查那些不可能的情况。
假设有一个函数可以计算折扣后的商品价格:
def calculate_discount(price, discount):
discounted_price = price - [discount*price]
assert 0 <= discounted_price <= price
return discounted_price
在这里,Discounted_price永远不能小于0且大于实际价格。因此,如果违反了上述条件,则assert会引发Assertion Error,这将有助于开发人员识别出某些不可能的事情发生了。
希望能帮助到你 :)
Python assert is basically a debugging aid which test condition for internal self-check of your code. Assert makes debugging really easy when your code gets into impossible edge cases. Assert check those impossible cases.
Let’s say there is a function to calculate price of item after discount :
def calculate_discount(price, discount):
discounted_price = price - [discount*price]
assert 0 <= discounted_price <= price
return discounted_price
here, discounted_price can never be less than 0 and greater than actual price. So, in case the above condition is violated assert raises an Assertion Error, which helps the developer to identify that something impossible had happened.
Hope it helps :)
回答 14
My short explanation is:
assert
raises AssertionError
if expression is false, otherwise just continues the code, and if there’s a comma whatever it is it will be AssertionError: whatever after comma
, and to code is like: raise AssertionError(whatever after comma)
A related tutorial about this:
https://www.tutorialspoint.com/python/assertions_in_python.htm
回答 15
在Pycharm中,如果assert
与一起使用isinstance
来声明对象的类型,它将使您在编码时可以访问父对象的方法和属性,它将自动自动完成。
例如,假设self.object1.object2
是一个MyClass
对象。
import MyClasss
def code_it(self):
testObject = self.object1.object2 # at this point, program doesn't know that testObject is a MyClass object yet
assert isinstance(testObject , MyClasss) # now the program knows testObject is a MyClass object
testObject.do_it() # from this point on, PyCharm will be able to auto-complete when you are working on testObject
In Pycharm, if you use assert
along with isinstance
to declare an object’s type, it will let you access the methods and attributes of the parent object while you are coding, it will auto-complete automatically.
For example, let’s say self.object1.object2
is a MyClass
object.
import MyClasss
def code_it(self):
testObject = self.object1.object2 # at this point, program doesn't know that testObject is a MyClass object yet
assert isinstance(testObject , MyClasss) # now the program knows testObject is a MyClass object
testObject.do_it() # from this point on, PyCharm will be able to auto-complete when you are working on testObject
回答 16
如在其他答案中所写,assert
语句用于检查给定点的程序状态。
我不会重复有关关联消息,括号或-O
选项和__debug__
常量的内容。另请查阅文档以获取第一手信息。我将重点关注您的问题:的用途是assert
什么?更准确地说,何时(何时不该使用)assert
?
该assert
语句对于调试程序很有用,但不鼓励检查用户输入。我使用以下经验法则:保留断言以检测这种不应该发生的情况。用户输入可能不正确,例如密码太短,但这不是不应该发生的情况。如果圆的直径不是其半径的两倍,则在这种情况下不应该发生。
最有趣的,在我脑海里,使用的assert
是由灵感
合同编程为[面向对象的软件建设]由B.迈耶描述(
https://www.eiffel.org/doc/eiffel/Object-Oriented_Software_Construction% 2C_2nd_Edition
)并以[Eiffel编程语言](https://en.wikipedia.org/wiki/Eiffel_ (programming_language
))实施。您不能使用该assert
语句通过合同完全模拟编程,但是保持意图很有趣。
这是一个例子。想象一下,您必须编写一个head
函数(例如head
Haskell中的[ 函数](
http://www.zvon.org/other/haskell/Outputprelude/head_f.html))。给出的规范是:“如果列表不为空,则返回列表的第一项”。查看以下实现:
>>> def head1(xs): return xs[0]
和
>>> def head2(xs):
... if len(xs) > 0:
... return xs[0]
... else:
... return None
(是的,可以写成return xs[0] if xs else None
,但这不是重点)。
如果列表不为空,则两个函数的结果相同,并且此结果正确:
>>> head1([1, 2, 3]) == head2([1, 2, 3]) == 1
True
因此,这两种实现都是(我希望)正确的。当您尝试采用空列表的标题时,它们会有所不同:
>>> head1([])
Traceback (most recent call last):
...
IndexError: list index out of range
但:
>>> head2([]) is None
True
同样,这两种实现都是正确的,因为没有人应该将空列表传递给这些函数(我们超出了规范)。那是一个不正确的电话,但是如果您进行这样的电话,任何事情都会发生。一个函数引发异常,另一个函数返回一个特殊值。最重要的是:我们不能依靠这种行为。如果xs
为空,则可以使用:
print(head2(xs))
但这将使程序崩溃:
print(head1(xs))
为避免意外,我想知道何时将一些意外的参数传递给函数。换句话说:我想知道何时可观察的行为不可靠,因为它取决于实现而不是规范。当然,我可以阅读规范,但是程序员并不总是仔细阅读文档。
想象一下,如果我有一种方法可以将规范插入代码中以达到以下效果:当我违反规范时,例如,通过向传递一个空列表head
,我会得到警告。这将对编写正确的(即符合规范的)程序有很大的帮助。这就是assert
进入现场的地方:
>>> def head1(xs):
... assert len(xs) > 0, "The list must not be empty"
... return xs[0]
和
>>> def head2(xs):
... assert len(xs) > 0, "The list must not be empty"
... if len(xs) > 0:
... return xs[0]
... else:
... return None
现在,我们有:
>>> head1([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
和:
>>> head2([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
请注意,它head1
抛出一个AssertionError
,而不是IndexError
。这很重要,因为an AssertionError
并不是任何运行时错误:它表示违反规范。我想要警告,但出现错误。幸运的是,我可以禁用该检查(使用该-O
选项),但后果自负。我会做到的,崩溃真的很昂贵,并且希望最好。想象一下,我的程序嵌入在穿过黑洞的宇宙飞船中。我将禁用断言,并希望该程序足够健壮,以免崩溃的时间尽可能长。
此示例仅与前提条件有关,因为您可以使用它assert
来检查后置条件(返回值和/或状态)和不变式(类的状态)。请注意,检查后置条件和不变量with assert
可能很麻烦:
- 对于后置条件,需要将返回值分配给变量,并且如果要处理方法,则可能需要存储对象的初始状态;
- 对于不变式,您必须在方法调用之前和之后检查状态。
您不会拥有像Eiffel那样复杂的功能,但是可以提高程序的整体质量。
总而言之,该assert
语句是检测这种不应该发生的情况的便捷方法。违反规范(例如,向传递一个空列表head
)是头等舱,这种情况不应该发生。因此,尽管该assert
语句可用于检测任何意外情况,但这是确保满足规范的一种特权方式。一旦将assert
语句插入代码中以表示规范,我们就可以希望您提高了程序的质量,因为将报告错误的参数,错误的返回值,错误的类状态…。
As written in other answers, assert
statements are used to check the state of
the program at a given point.
I won’t repeat what was said about associated
message, parentheses, or -O
option and __debug__
constant. Check also the
doc for first
hand information. I will focus on your question: what is the use of assert
?
More precisely, when (and when not) should one use assert
?
The assert
statements are useful to debug a program, but discouraged to check user
input. I use the following rule of thumb: keep assertions to detect a this
should not happen situation. A user
input may be incorrect, e.g. a password too short, but this is not a this
should not happen case. If the diameter of a circle is not twice as large as its
radius, you are in a this should not happen case.
The most interesting, in my mind, use of assert
is inspired by the
programming by contract as
described by B. Meyer in [Object-Oriented Software Construction](
https://www.eiffel.org/doc/eiffel/Object-Oriented_Software_Construction%2C_2nd_Edition
) and implemented in the [Eiffel programming language](
https://en.wikipedia.org/wiki/Eiffel_(programming_language)). You can’t fully
emulate programming by contract using the assert
statement, but it’s
interesting to keep the intent.
Here’s an example. Imagine you have to write a head
function (like the
[head
function in Haskell](
http://www.zvon.org/other/haskell/Outputprelude/head_f.html)). The
specification you are given is: “if the list is not empty, return the
first item of a list”. Look at the following implementations:
>>> def head1(xs): return xs[0]
And
>>> def head2(xs):
... if len(xs) > 0:
... return xs[0]
... else:
... return None
(Yes, this can be written as return xs[0] if xs else None
, but that’s not the point).
If the list is not empty, both functions have the same result and this result is correct:
>>> head1([1, 2, 3]) == head2([1, 2, 3]) == 1
True
Hence, both implementations are (I hope) correct. They differ when you try to take the head item of an empty list:
>>> head1([])
Traceback (most recent call last):
...
IndexError: list index out of range
But:
>>> head2([]) is None
True
Again, both implementations are correct, because no one should pass an empty
list to these functions (we are out of the specification). That’s an
incorrect call, but if you do such a call, anything can happen.
One function raises an exception, the other returns a special value.
The most important is: we can’t rely on this behavior. If xs
is empty,
this will work:
print(head2(xs))
But this will crash the program:
print(head1(xs))
To avoid some surprises, I would like to know when I’m passing some unexpected argument to a function. In other words: I would like to know when the observable behavior is not reliable, because it depends on the implementation, not on the specification. Of course, I can read the specification, but programmers do not always read carefully the docs.
Imagine if I had a way to insert the specification into the code to get the
following effect: when I violate the specification, e.g by passing an empty
list to head
, I get a warning. That would be a great help to write a correct
(i.e. compliant with the specification) program. And that’s where assert
enters on the scene:
>>> def head1(xs):
... assert len(xs) > 0, "The list must not be empty"
... return xs[0]
And
>>> def head2(xs):
... assert len(xs) > 0, "The list must not be empty"
... if len(xs) > 0:
... return xs[0]
... else:
... return None
Now, we have:
>>> head1([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
And:
>>> head2([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
Note that head1
throws an AssertionError
, not an IndexError
. That’s
important because an AssertionError
is not any runtime error: it signals a
violation of the specification. I wanted a warning, but I get an error.
Fortunately, I can disable the check (using the -O
option),
but at my own risks. I will do it a crash is really expensive, and hope for the
best. Imagine my program is embedded in a spaceship that travels through a
black hole. I will disable assertions and hope the program is robust enough
to not crash as long as possible.
This example was only about preconditions, be you can use assert
to check
postconditions (the return value and/or the state) and invariants (state of a
class). Note that checking postconditions and invariants with assert
can be
cumbersome:
- for postconditions, you need to assign the return value to a variable, and maybe to store the iniial state of the object if you are dealing with a method;
- for invariants, you have to check the state before and after a method call.
You won’t have something as sophisticated as Eiffel, but you can however improve the overall quality of a program.
To summarize, the assert
statement is a convenient way to detect a this
should not happen situation. Violations of the specification (e.g. passing
an empty list to head
) are first class this should not happen situations.
Hence, while the assert
statement may be used to detect any unexpected situation,
it is a privilegied way to ensure that the specification is fulfilled.
Once you have inserted assert
statements into the code to represent the
specification, we can hope you have improved the quality of the program because
incorrect arguments, incorrect return values, incorrect states of a class…,
will be reported.
回答 17
格式:assert Expression [,arguments]当assert遇到一条语句时,Python计算该表达式。如果该语句不为true,则会引发异常(assertionError)。如果断言失败,Python将ArgumentExpression用作AssertionError的参数。可以使用try-except语句像其他任何异常一样捕获和处理AssertionError异常,但是如果不处理,它们将终止程序并产生回溯。例:
def KelvinToFahrenheit(Temperature):
assert (Temperature >= 0),"Colder than absolute zero!"
return ((Temperature-273)*1.8)+32
print KelvinToFahrenheit(273)
print int(KelvinToFahrenheit(505.78))
print KelvinToFahrenheit(-5)
执行以上代码后,将产生以下结果:
32.0
451
Traceback (most recent call last):
File "test.py", line 9, in <module>
print KelvinToFahrenheit(-5)
File "test.py", line 4, in KelvinToFahrenheit
assert (Temperature >= 0),"Colder than absolute zero!"
AssertionError: Colder than absolute zero!
format : assert Expression[,arguments] When assert encounters a statement,Python evaluates the expression.If the statement is not true,an exception is raised(assertionError). If the assertion fails, Python uses ArgumentExpression as the argument for the AssertionError. AssertionError exceptions can be caught and handled like any other exception using the try-except statement, but if not handled, they will terminate the program and produce a traceback. Example:
def KelvinToFahrenheit(Temperature):
assert (Temperature >= 0),"Colder than absolute zero!"
return ((Temperature-273)*1.8)+32
print KelvinToFahrenheit(273)
print int(KelvinToFahrenheit(505.78))
print KelvinToFahrenheit(-5)
When the above code is executed, it produces the following result:
32.0
451
Traceback (most recent call last):
File "test.py", line 9, in <module>
print KelvinToFahrenheit(-5)
File "test.py", line 4, in KelvinToFahrenheit
assert (Temperature >= 0),"Colder than absolute zero!"
AssertionError: Colder than absolute zero!
回答 18
def getUser(self, id, Email):
user_key = id and id or Email
assert user_key
可用于确保在函数调用中传递参数。
def getUser(self, id, Email):
user_key = id and id or Email
assert user_key
Can be used to ensure parameters are passed in the function call.
回答 19
>>>this_is_very_complex_function_result = 9
>>>c = this_is_very_complex_function_result
>>>test_us = (c < 4)
>>> #first we try without assert
>>>if test_us == True:
print("YES! I am right!")
else:
print("I am Wrong, but the program still RUNS!")
I am Wrong, but the program still RUNS!
>>> #now we try with assert
>>> assert test_us
Traceback (most recent call last):
File "<pyshell#52>", line 1, in <module>
assert test_us
AssertionError
>>>
>>>this_is_very_complex_function_result = 9
>>>c = this_is_very_complex_function_result
>>>test_us = (c < 4)
>>> #first we try without assert
>>>if test_us == True:
print("YES! I am right!")
else:
print("I am Wrong, but the program still RUNS!")
I am Wrong, but the program still RUNS!
>>> #now we try with assert
>>> assert test_us
Traceback (most recent call last):
File "<pyshell#52>", line 1, in <module>
assert test_us
AssertionError
>>>
回答 20
基本上,assert关键字的含义是,如果条件不成立,则通过assertionerror进行处理,否则例如在python中继续进行。
代码1
a=5
b=6
assert a==b
输出:
assert a==b
AssertionError
代码2
a=5
b=5
assert a==b
输出:
Process finished with exit code 0
Basically the assert keyword meaning is that if the condition is not true then it through an assertionerror else it continue for example in python.
code-1
a=5
b=6
assert a==b
OUTPUT:
assert a==b
AssertionError
code-2
a=5
b=5
assert a==b
OUTPUT:
Process finished with exit code 0
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。