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


assert语句几乎存在于每一种编程语言中。它有两个主要用途:

它有助于在程序的早期(原因很清楚的时候)检测问题,而不是在其他一些操作失败的时候。例如,Python中的类型错误如果没有在早期被捕获,可能会在实际引发异常之前经历几层代码。 对于阅读代码的其他开发人员来说,它可以作为文档使用,他们看到断言后可以自信地说从现在开始它的条件是成立的。

当你……

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。这是一个声明。如果执行断言(condition, message),则运行断言时将使用(condition, message)元组作为第一个参数。

至于禁用它们,当以优化模式运行python时,其中__debug__为False, assert语句将被忽略。只需要传递-O标志:

python -O script.py

相关文档请参见这里。


从文档:

断言语句是向程序中插入调试断言的一种方便方法

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


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

您可以在交互式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。


正如其他答案所指出的,assert类似于在给定条件不为真时抛出异常。一个重要的区别是,如果使用优化选项-O编译代码,断言语句将被忽略。文档说断言表达式可以更好地描述为等效于

if __debug__:
   if not expression: raise AssertionError

如果你想彻底测试你的代码,然后在你高兴地看到你的断言案例都没有失败时发布一个优化版本,这可能是有用的——当优化打开时,__debug__变量变成False,条件将停止计算。如果您依赖断言,而没有意识到断言已经消失,该特性还可以发现这一点。


assert语句有两种形式。

简单形式assert <expression>相当于

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

扩展形式assert <expression1>, <expression2>等价于

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

这是一个简单的例子,保存到文件(比如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

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

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

如果assert后的语句为真,则程序继续执行,但如果assert后的语句为假,则程序报错。就这么简单。

例如:

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

格式: 断言表达式(参数) 当assert遇到语句时,Python对表达式求值。如果语句不为真,则引发异常(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!    

def getUser(self, id, Email):

    user_key = id and id or Email

    assert user_key

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


注意括号。正如在其他回答中指出的那样,在Python 3中,assert仍然是一个语句,因此通过与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。


如果你想知道python中保留函数的确切功能,输入help(enter_keyword)

如果您正在输入保留关键字,请确保将其输入为字符串。


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

断言并不是为了表明预期的错误条件,比如“文件未找到”,用户可以采取纠正措施(或者只是重试)。

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

如果您的程序没有错误,这些情况将永远不会发生。但如果其中一个确实发生了,程序将崩溃,并提示一个断言错误,告诉您究竟触发了哪个“不可能”条件。这使得跟踪和修复程序中的错误变得更加容易。

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

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


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

如果assert关键字后面的代码为False, Python中的assert关键字将引发AssertionError。如果没有,它继续什么都没有发生。

示例1:

a = 5
b = 6

assert a == b

输出:

AssertionError

这是因为,很明显,a不等于b。 如果你想在代码中引发一个异常,这是特别有用的。

def get_dict_key(d, k):
    try:
        assert k in d
        return d[k]
    except Exception:
        print("Key must be in dict.")

上面的示例实际上是无用的,但是请记住,它主要用于调试目的,因此您可以跟踪错误。


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

假设有一个函数计算商品折扣后的价格:

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

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

希望能有所帮助。


我的简单解释是:

如果表达式为假,assert会引发AssertionError,否则只是继续代码,如果有逗号,无论它是什么,它都会在逗号后引发AssertionError: whatever,而to code则是:引发AssertionError(逗号后的whatever)

相关教程:

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


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

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

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

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

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


assert语句几乎存在于每一种编程语言中。它有助于在程序的早期(原因很清楚的时候)检测问题,而不是在稍后作为其他操作的副作用检测问题。他们总是期待一个真实的条件。

当你这样做的时候:

assert condition

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

在Python中,assert表达式等价于:

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语句使用了两个条件。因此,不要用圆括号把它们括起来作为一个明显的建议。如果你这样做:

assert (condition, message)

例子:

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

你将使用(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:

* assert被禁用;

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

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

*和,__debug__被设置为False;

值2:禁用一个东西

*文档字符串被禁用;

因此,使用assert语句来验证一种预期的数据是极其危险的,甚至意味着存在一些安全问题。然后,如果你需要验证一些权限,我建议你提出AuthError代替。作为有效的前置条件,assert通常由程序员在不与用户直接交互的库或模块上使用。


正如在其他回答中所写的那样,assert语句用于检查 程序:在给定点上的程序

我就不重复刚才说的相关内容了 message,括号,或-O选项和__debug__常量。同时查看 首先是医生 手的信息。我将集中讨论你的问题:assert有什么用? 更准确地说,什么时候(什么时候不)应该使用assert?

assert语句对调试程序很有用,但不建议检查user 输入。我使用以下经验法则:keep断言来检测this 不应该发生的情况。一个用户 输入可能不正确,例如密码太短,但这不是一个this 不应该发生的情况。如果一个圆的直径不是它的两倍大 半径,这是不应该发生的情况。

在我看来,assert最有趣的用法是受到 通过合同编程 由B. Meyer在[面向对象软件构造]中描述( https://www.eiffel.org/doc/eiffel/Object-Oriented_Software_Construction%2C_2nd_Edition ),并以[Eiffel编程语言]( https://en.wikipedia.org/wiki/Eiffel_ (programming_language))。你不能完全 使用assert语句模拟契约编程,但它是 保持意图很有趣。

举个例子。假设您必须编写一个head函数(如 [Haskell中的头部功能]( http://www.zvon.org/other/haskell/Outputprelude/head_f.html))。的 给出的规范是:“如果列表不为空,则返回 清单的第一项”。看看下面的实现:

>>> def head1(xs): return xs[0]

And

>>> def head2(xs):
...     if len(xs) > 0:
...         return xs[0]
...     else:
...         return None

(是的,如果xs else None,这可以写成return xs[0],但这不是重点)。

如果列表不为空,则两个函数的结果与此结果相同 是正确的:

>>> head1([1, 2, 3]) == head2([1, 2, 3]) == 1
True

因此,两种实现(我希望)都是正确的。当你尝试的时候,它们是不同的 取一个空列表的头项:

>>> head1([])
Traceback (most recent call last):
...
IndexError: list index out of range

But:

>>> head2([]) is None
True

同样,这两种实现都是正确的,因为不应该传递空值 列出这些函数(我们不在规范范围内)。这是一个 不正确的判断,但如果你做了这样的判断,任何事情都有可能发生。 一个函数引发异常,另一个函数返回一个特殊值。 最重要的是:我们不能依赖这种行为。如果xs是空的, 这是可行的:

print(head2(xs))

但是这会使程序崩溃:

print(head1(xs))

为了避免一些意外,我想知道我什么时候经过一些意外 函数的参数。换句话说:我想知道什么时候可观察到 行为是不可靠的,因为它依赖于实现,而不是规范。 当然,我可以阅读规范,但程序员并不总是仔细阅读 文档。

想象一下,如果我有一种方法将规范插入到代码中以获得 以下效果:当我违反规范,例如通过传递一个空 清单上的人头,我会收到警告。写正确的答案会有很大的帮助 (即符合规范)程序。这就是assert的地方 进入现场:

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

现在,我们有:

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

注意,head1抛出AssertionError,而不是IndexError。这是 因为AssertionError不是任何运行时错误:它标志着一个 违反规范。我想要一个警告,但是我得到了一个错误。 幸运的是,我可以禁用检查(使用-O选项), 但风险由我自己承担。我将会做一个坠毁真的很贵,并希望 最好的想象一下,我的程序被嵌入到一艘宇宙飞船中,它穿越 黑洞。我将禁用断言,并希望程序足够健壮 尽量不要崩溃。

这个例子只是关于前提条件的,你可以使用assert来检查 后置条件(返回值和/或状态)和不变量(对象的状态) 类)。注意,使用assert检查后置条件和不变量可以 麻烦:

对于后置条件,您需要将返回值赋给一个变量,以及 也许是用来存储对象的初始状态如果你在处理一个方法; 对于不变量,必须在方法调用之前和之后检查状态。

你不会有像埃菲尔铁塔一样复杂的东西,但你可以 提高程序的整体质量。


总之,assert语句是检测this的一种方便方法 不应该发生的情况。违反规范(例如:通过 一个空列表头)是第一类这种不应该发生的情况。 因此,虽然assert语句可用于检测任何意外情况, 这是一种确保满足规范的特权方式。 在代码中插入断言语句以表示 规格,我们可以希望您已经提高了程序的质量,因为 不正确的参数,不正确的返回值,不正确的类状态… 将被报告。


在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

断言是在我们的程序中自信地陈述事实的语句。

语法:assert <条件>或assert <条件>,<错误消息>

它有一个条件/表达式,它应该总是为真。如果条件为false, assert语句将停止程序并抛出AssertionError错误消息。你的断言表达式将是你不希望在程序中出现的东西。

e.g.

Assert <条件>——使用Assert而没有<错误消息> var = int(输入("输入值1-9包含:")) 断言var != 0 打印(var) 输出: 如果输入为0: AssertionError 如果输入为1: 1 断言<条件>,<错误消息>——使用带有<错误消息>的断言 var = int(输入("输入值1-9包含:")) 断言var !=0,"输入不能为零" 打印(var) 输出: 如果输入为0: AssertionError:输入不能为零 如果输入为1: 1

重点:

它被用作调试工具。 它接受一个表达式和一个可选消息。 它几乎存在于每一种编程语言中


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

这里有很好的答案,但不是问题的第二部分。尽管有多年的实践经验,但我直到最近才明白断言的目的。

其他人已经解释了如何使用assert,所以我非常简短。下面是它的用法:

assert condition, "error message"

不要使用圆括号,assert是关键字,不是函数。

assert (condition, "error message")  # wrong: this never fails!

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

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

这里有一个很好的例子来把它们联系在一起。让我们假设您希望在代码中有一个特殊的数字类,它表示称为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)   

如你所见,我用了两个if…:提高……用于输入验证和函数末尾的断言。这似乎是多余的,但仅在这个微不足道的示例中!假设函数稍微长一些,也更复杂一些,因此您是否正确地验证了输入并不明显。末尾的断言确保检测到验证代码中的错误。它还使另一个程序员更清楚地了解验证代码的意图,而不是简单的注释。

总之:像使用注释一样使用assert。到处使用!它很便宜,如果它成为用户的性能问题,你可以在发行版中使用python -O关闭它。