在Python中使用“assert”有什么用?

问题描述 投票:780回答:19

我一直在阅读一些源代码,在一些地方我已经看到了assert的用法。

这究竟是什么意思?它的用途是什么?

python assert assertions
19个回答
912
投票

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

有关相关文档,请参阅here


6
投票

如果assert之后的语句为true,则程序继续,但如果assert之后的语句为false,则程序会给出错误。就那么简单。

e.f.:

assert 1>0   #normal execution
assert 0>1   #Traceback (most recent call last):
             #File "<pyshell#11>", line 1, in <module>
             #assert 0>1
             #AssertionError

3
投票

正如C2 Wiki简明扼要地总结:

断言是程序中特定点的布尔表达式,除非程序中存在错误,否则它将为真。

您可以使用assert语句来记录您对特定程序点的代码的理解。例如,您可以记录有关输入(前置条件),程序状态(不变量)或输出(后置条件)的假设或保证。

如果您的断言失败,这是一个警告您(或您的继任者),当您编写程序时,您对该程序的理解是错误的,并且它可能包含错误。

有关更多信息,John Regehr在Use of Assertions上有一篇很棒的博客文章,它也适用于Python assert声明。


2
投票

如果你想知道python中保留函数究竟是什么,请输入help(enter_keyword)

确保输入的保留关键字是否以字符串形式输入。


1
投票

Python断言基本上是一个调试辅助工具,用于测试代码内部自检的条件。当代码进入不可能的边缘情况时,Assert使调试变得非常容易。断言检查那些不可能的情况。

假设有折扣后计算物品价格的功能:

def calculate_discount(price, discount):
    discounted_price = price - [discount*price]
    assert 0 <= discounted_price <= price
    return discounted_price

在这里,discounted_price永远不会小于0且大于实际价格。因此,如果上述条件被违反,断言会引发断言错误,这有助于开发人员识别出不可能发生的事情。

希望能帮助到你 :)


1
投票

我的简短解释是:

  • assert如果表达式为false则引发AssertionError,否则只是继续代码,如果有逗号它将是AssertionError: whatever after comma,代码就像:raise AssertionError(whatever after comma)

关于此的相关教程:

https://www.tutorialspoint.com/python/assertions_in_python.htm


0
投票

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

在使用它们之前,有一些注意事项,主要是那些认为在assertif声明之间切换的人。使用assert的目的是在程序验证条件并返回应该立即停止程序的值而不是采取某种替代方法来绕过错误的情况下:

1.括号

您可能已经注意到,assert语句使用两个条件。因此,不要使用括号将它们作为一个明显的建议。如果您这样做:

assert (condition, message)

例:

>>> assert (1==2, 1==1)
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?

你将使用assert运行(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语句来执行数据处理或数据验证,因为可以使用-O-OO标志在Python初始化时关闭此语句 - 分别表示值1,2和0(默认值) - 或PYTHONOPTIMIZE环境变量。

价值1:

*断言被禁用;

*使用.pyo扩展而不是.pyc生成字节码文件;

* sys.flags.optimize设为1(True);

*和__debug__设为False;

值2:禁用一个以上的东西

*文档字符串被禁用;

因此,使用assert语句验证某种预期数据是非常危险的,甚至暗示某些安全问题。然后,如果你需要验证一些权限我建议你改为raise AuthError。作为一种前期有效的方法,程序员通常会在没有用户直接交互的库或模块上使用assert


-2
投票

format: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!    

-2
投票
def getUser(self, id, Email):

    user_key = id and id or Email

    assert user_key

可用于确保在函数调用中传递参数。


-4
投票
>>>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
>>> 

-4
投票

基本上断言关键字含义是如果条件不是真的那么它通过断言错误,否则它继续例如在python中。

代码-1

a=5

b=6

assert a==b

OUTPUT:

assert a==b

AssertionError

代码-2-

a=5

b=5

assert a==b

OUTPUT:

Process finished with exit code 0

368
投票

注意括号。正如上面已经指出的那样,in Python 3, assert is still a statement,所以与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


120
投票

正如其他答案所指出的那样,assert类似于在给定条件不成立时抛出异常。一个重要的区别是,如果使用优化选项编译代码,则会忽略assert语句。 documentation说,assert expression可以更好地被描述为相当于

if __debug__:
   if not expression: raise AssertionError

如果您想要彻底测试代码,然后在您对所有断言案例都没有失败感到高兴时发布优化版本,这将非常有用 - 当优化开启时,__debug__变量变为False,条件将停止进行评估。如果你依赖断言并且没有意识到它们已经消失,这个功能也会让你感到惊讶。


49
投票

其他人已经为您提供了文档链接。

您可以在交互式shell中尝试以下操作:

>>> 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


38
投票

Python中断言的目的是告知开发人员程序中不可恢复的错误。

断言并非旨在表示预期的错误情况,例如“未找到文件”,用户可以采取纠正措施(或者只是重试)。

另一种看待它的方法是说断言是代码中的内部自检。他们通过在代码中声明一些不可能的条件来工作。如果这些条件不成立,则意味着程序中存在错误。

如果您的程序没有错误,则永远不会出现这些情况。但如果其中一个确实发生,程序将崩溃并出现断言错误,告诉您确切触发了哪个“不可能”的情况。这样可以更轻松地跟踪和修复程序中的错误。

以下是我写的a tutorial on Python’s assertions摘要:

Python的assert语句是一种调试辅助工具,而不是处理运行时错误的机制。使用断言的目的是让开发人员更快地找到错误的可能根本原因。除非程序中存在错误,否则永远不应该引发断言错误。


17
投票

断言语句有两种形式。

简单的形式,assert <expression>,相当于

if __​debug__:
    if not <expression>: raise AssertionError

扩展形式assert <expression1>, <expression2>相当于

if __​debug__:
    if not <expression1>: raise AssertionError, <expression2>

15
投票

断言是一种系统的方法,用于检查程序的内部状态是否与程序员预期的一样,目的是捕获错误。请参阅下面的示例。

>>> 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!
>>> 

13
投票

来自docs:

Assert statements are a convenient way to insert debugging assertions into a program

在这里你可以阅读更多:http://docs.python.org/release/2.5.2/ref/assert.html


7
投票

这是一个简单的例子,将其保存在文件中(假设为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
© www.soinside.com 2019 - 2024. All rights reserved.