在Python中使用"assert"有什么用?

Hos*_*ein 860 python assert assertions

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

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

sle*_*ica 993

assert语句几乎存在于每种编程语言中.它有助于在程序的早期发现问题,原因很明显,而不是后来作为其他一些操作的副作用.

当你这样做......

assert condition
Run Code Online (Sandbox Code Playgroud)

...您告诉程序测试该条件,如果条件为假,则立即触发错误.

在Python中,它大致相当于:

if not condition:
    raise AssertionError()
Run Code Online (Sandbox Code Playgroud)

在Python shell中尝试:

>>> assert True # nothing happens
>>> assert False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
Run Code Online (Sandbox Code Playgroud)

断言可以包含可选消息,您可以在运行解释器时禁用它们.

要在断言失败时打印消息:

assert False, "Oh no! This assertion failed!"
Run Code Online (Sandbox Code Playgroud)

千万不能使用括号调用assert的功能等.这是一份声明.如果你这样做,assert(condition, message)你将assert使用(condition, message)元组作为第一个参数运行.

至于禁用它们,运行时,python在优化模式,其中__debug__False,断言语句将被忽略.只要通过-O旗帜:

python -O script.py
Run Code Online (Sandbox Code Playgroud)

请参阅此处获取相关文档.

  • Nit:断言是一个声明,而不是一个函数.并且[不像print](http://legacy.python.org/dev/peps/pep-3105/),在Python 3中它[仍然是一个声明](https://docs.python.org/3/reference/ simple_stmts.html#语法令牌assert_stmt). (77认同)
  • 可选消息的语法:`assert False,"你断言了一些错误的东西."`另见[这个答案](http://stackoverflow.com/a/30770447/1599229)的陷阱. (65认同)
  • 断言的目的经常被误解。它们并不像建议的那样用于早期测试条件,也不是测试表达式的语法糖。它们的目的是“断言”程序中某些点的某些条件为真,目的是帮助程序员了解这些点上的系统状态。例如,如果在函数顶部我看到一个“assert arg”语句,那么我毫无疑问地知道 (arg is None) 对于该函数中的任何后续语句来说都是无效状态,从而减少了我拥有的状态集考虑。 (26认同)
  • 完全无法得到这个答案如何得到这么多的选票,实际上其他人的答案也是如此.问题是"在Python中使用"断言"是什么用途?",所以它要问:何时使用,或者更确切地说:`assert`的使用场景是什么,但在阅读完所有答案之后,我什么都没有我想要! (8认同)
  • @ alpha_989 a)它更短更易读,b)你可以在运行解释器时禁用断言语句(手册`if`不是这样).阅读文档了解更多信息:) (4认同)
  • 如果我可以使用`if not condition:raise AssertError()`,我为什么要使用assert?有没有什么条件断言更好,而不仅仅是一个简短形式的`if not condition`陈述? (3认同)
  • @Chaine assert 的意思是“确保 *something” 为真。所以 assert a == 3 将确保 a 等于 3;如果 a 不等于 3(即 a==3 为 False),那么它将引发错误 (2认同)

Evg*_*eev 396

注意括号.正如上面已经指出的那样,在Python 3中,assert仍然是一个声明,所以通过类比print(..),可以将其推断为assert(..)或者raise(..)你不应该推断.

这很重要,因为:

assert(2 + 2 == 5, "Houston we've got a problem")
Run Code Online (Sandbox Code Playgroud)

不会有用,不像

assert 2 + 2 == 5, "Houston we've got a problem"
Run Code Online (Sandbox Code Playgroud)

第一个不起作用的原因是bool( (False, "Houston we've got a problem") )评估为True.

在声明中assert(False),这些只是多余的括号False,它们评估其内容.但是assert(False,)括号现在是一个元组,并且非空元组True在布尔上下文中求值.

  • 我来到这里寻找关于parens和关注消息的确切信息.谢谢. (14认同)
  • 但是`断言(2 + 2 = 5),"休斯顿我们遇到了问题""应该没问题,是吗? (5认同)
  • @SherylHohman你也可以尝试自己运行它,看看它是否有效 (4认同)
  • `assert(2 + 2 = 5),"休斯顿我们遇到了一个问题"``无法工作......但它与断言语句无关,这很好.你的病情不会起作用,因为它不是病情.缺少第二个`=`. (3认同)
  • 不要忘记,人们经常使用括号进行符合PEP 8的隐式行继续.另外也不要忘记,元组不是由括号定义,而是由逗号的存在定义(元组除了为了实现目的而与parens无关)运算符优先级). (2认同)

Nei*_*ass 128

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

if __debug__:
   if not expression: raise AssertionError
Run Code Online (Sandbox Code Playgroud)

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


Bal*_*arq 50

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

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

>>> assert 5 > 2
>>> assert 2 > 5
Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
builtins.AssertionError:
Run Code Online (Sandbox Code Playgroud)

第一个语句什么都不做,而第二个语句引发异常.这是第一个提示:断言对于检查在代码的给定位置(通常是开头(前置条件)和函数末尾(后置条件))应该为真的条件很有用.

断言实际上与合同编程密切相关,这是一个非常有用的工程实践:

http://en.wikipedia.org/wiki/Design_by_contract.

  • 失去了parens,断言不是一个功能. (19认同)
  • 断言实际上可以追溯到很久(早在"合同"之前)到图灵,当时他写了一篇关于程序员如何处理创建正确程序相当艰巨任务的最早的论文.发现该论文留给读者作为练习,因为所有程序员都可以从熟悉他的工作中受益.:-) http://www.turingarchive.org/ (6认同)
  • 失去括号比看起来更重要。请参阅[下文](http://stackoverflow.com/a/30770447/1143274)。 (3认同)

dba*_*der 41

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

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

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

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

以下是我写的关于Python断言的教程的摘要:

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

  • @LaryxDecidua 不,你可以在我的网站上阅读它,该教程是公开的。如果您对时事通讯不感兴趣,只需点击转义键或单击小“x”符号。希望这可以帮助 :-) (2认同)

Boh*_*dan 17

断言语句有两种形式.

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

if __?debug__:
    if not <expression>: raise AssertionError
Run Code Online (Sandbox Code Playgroud)

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

if __?debug__:
    if not <expression1>: raise AssertionError, <expression2>
Run Code Online (Sandbox Code Playgroud)


olq*_*plo 16

断言是什么意思?它是如何使用的?

这里有很好的答案,但不是问题的第二部分。尽管有多年的实践经验,但我最近才了解断言的用途。

其他人已经解释了如何assert使用,所以我超级简短。这是你如何使用它:

assert condition, "error message"
Run Code Online (Sandbox Code Playgroud)

并且不要使用括号,assert 是一个关键字,而不是一个函数。

assert (condition, "error message")  # wrong: this never fails!
Run Code Online (Sandbox Code Playgroud)

这里给出了如何使用断言的一个很好的解释:http://wiki.c2.com/?WhatAreAssertions 要点是在代码中assert声明不变量。不变量是永远不应违反的条件,除非代码中存在错误。将它们视为可执行文档。这与面向对象编程如何封装来自外部世界的代码密切相关。

简而言之:您应该在代码中为其他开发人员使用像注释一样的断言。但它比注释更好,“注释”实际上是在调试模式下检查的!如果断言被删除后你的程序就不能正常工作,那么你就错误地使用了它。事实上,assert如果打开优化 ( python -O),Python 将忽略所有 s。所以不要依赖他们的存在。特别是,不要使用断言来验证用户输入。相反,引发异常。

这是一个将它们联系在一起的很好的例子。假设您希望在代码中拥有一个特殊的数字类,它表示称为 的正整数PositiveInt。你为什么想要那个?您有许多使用正整数作为参数的函数。通过PositiveInt在代码中使用,您不必在每个函数中一次又一次地检查输入是否有效。它由 保证PositiveInt。粗略的实现如下所示

class PositiveInt(int):
    # int is immutable, so we have to override new and not init
    def __new__(cls, value):
        if value <= 0:
            raise ValueError(f"{value} is not positive")
        assert value > 0, "value must be positive"
        return super(PositiveInt, cls).__new__(cls, value)   
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我使用 anif ...: raise ...进行输入验证,并assert在函数末尾使用an 。这似乎是多余的,但仅在这个简单的例子中!想象一下,该函数有点长且更复杂,因此您是否正确验证输入并不明显。最后的断言可确保检测到验证代码中的错误。它还使其他程序员清楚验证代码的意图,而不仅仅是简单的注释。

总之assert像评论一样使用。到处使用它!它很便宜,如果它对您的用户来说成为性能问题,您可以在带有python -O.


Jac*_*ham 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!
>>> 
Run Code Online (Sandbox Code Playgroud)

  • 此外,断言通常可用于单元测试程序。http://stackoverflow.com/questions/1383/what-is-unit-testing (2认同)

gru*_*czy 14

来自docs:

Assert statements are a convenient way to insert debugging assertions into a program
Run Code Online (Sandbox Code Playgroud)

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


sla*_*yer 8

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

You can use the extended expression to pass an optional message:

if __debug__:
    if not (expression_1): raise AssertionError(expression_2)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

Example:

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

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"
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

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())
Run Code Online (Sandbox Code Playgroud)

* 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
Run Code Online (Sandbox Code Playgroud)

* 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
Run Code Online (Sandbox Code Playgroud)

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


Gau*_*wal 7

这是一个简单的例子,将其保存在文件中(假设为b.py)

def chkassert(num):
    assert type(num) == int


chkassert('a')
Run Code Online (Sandbox Code Playgroud)

和结果时 $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
Run Code Online (Sandbox Code Playgroud)


abe*_*312 6

如果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
Run Code Online (Sandbox Code Playgroud)


ava*_*sen 6

正如C2 Wiki上简要总结的那样:

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

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

如果您的断言失败,这会提醒您(或您的继任者),您在编写程序时对程序的理解是错误的,并且它可能包含错误。

有关更多信息,John Regehr 有一篇关于使用断言的精彩博客文章,它也适用于 Pythonassert语句。


ytp*_*lai 5

如果你想确切地知道 Python 中保留函数的作用,请输入help(enter_keyword)

确保您输入的保留关键字是作为字符串输入的。


alw*_*btc 5

在 Pycharm 中,如果你使用assertwithisinstance来声明一个对象的类型,它会让你在编码时访问父对象的方法和属性,它会自动完成。

例如,假设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
Run Code Online (Sandbox Code Playgroud)