Python 中的“assert”有什么用途?

2024-12-25 08:50:00
admin
原创
204
摘要:问题描述:是什么assert意思?怎么用?解决方案 1:该assert语句几乎存在于每种编程语言中。它有两个主要用途:Exception它有助于在程序早期发现问题,因为问题原因很明确,而不是等到其他操作失败后才发现。例如,如果在早期没有发现,Python 中的类型错误可能会经过几层代码才会真正引发错误。它可以...

问题描述:

是什么assert意思?怎么用?


解决方案 1:

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

  1. Exception它有助于在程序早期发现问题,因为问题原因很明确,而不是等到其他操作失败后才发现。例如,如果在早期没有发现,Python 中的类型错误可能会经过几层代码才会真正引发错误。

  2. 它可以作为其他开发人员阅读代码的文档,他们看到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优化模式下运行时,assert 语句将被忽略。只需传递__debug__标志即可:False`-O`

python -O script.py

请参阅此处查看相关文档。

解决方案 2:

注意括号。正如其他答案所指出的那样,在 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在布尔上下文中求值为。

解决方案 3:

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

if __debug__:
   if not expression: raise AssertionError

如果您想彻底测试代码,然后在满意地发现所有断言情况均未失败时发布优化版本,这将非常有用 - 当优化开启时,变量__debug__将变为 False,条件将停止评估。如果您依赖断言并且没有意识到它们已经消失,此功能也可能会让您措手不及。

解决方案 4:

Python 中断言的目的是通知开发人员程序中无法恢复的错误。

断言并不旨在发出预期的错误情况,例如“未找到文件”,用户可以采取纠正措施(或只是再试一次)。

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

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

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

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

解决方案 5:

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

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

解决方案 6:

来自文档:

断言语句是将调试断言插入程序的便捷方法

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

解决方案 7:

assert 是什么意思?如何使用?

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

其他人已经解释了如何assert使用,所以我就简单说一下。使用方法如下:

assert condition, "error message"

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

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

这里给出了如何使用断言的一个很好的解释: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)   

如您所见,我if ...: raise ...在输入验证中使用了,并在函数末尾使用了assert。这似乎是多余的,但仅限于这个简单的示例!想象一下,该函数更长更复杂,因此您无法明显看出是否已正确验证了输入。末尾的断言可确保检测到验证代码中的错误。它还使其他程序员更清楚地了解验证代码的意图,而不仅仅是简单的注释。

总结assert像注释一样使用。到处使用它!它很便宜,如果它成为用户的性能问题,您可以在发布时将其关闭python -O

解决方案 8:

assert 语句有两种形式。

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

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

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

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

解决方案 9:

断言是一种系统性方法,用于检查程序的内部状态是否符合程序员的预期,目的是发现错误。请参见下面的示例。

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

解决方案 10:

这是一个简单的例子,将其保存在文件中(假设为 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

解决方案 11:

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

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

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

如果您的断言失败,这会向您(或您的继任者)发出警报,表明您在编写程序时对程序的理解是错误的,并且程序中可能包含错误。

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

解决方案 12:

几乎每种编程语言都存在该assert语句。它有助于在程序的早期检测出问题,因为问题原因很明确,而不是在之后作为其他操作的副作用出现。它们总是期望出现某种True条件。

当你做类似的事情时:

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

在使用它们之前,需要注意一些注意事项,特别是对于那些想要在assertandif语句之间切换的人。使用的目的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.
  1. 调试目的


如果你对何时使用语句感到疑惑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']),\n            "Discounted prices cannot be lower than 0 "\n            "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
  1. 数据处理或数据验证


最重要的是不要依赖语句来执行数据处理或数据验证,因为可以在 Python 初始化时使用或标志(分别表示值 1、2 和 0(默认值))或环境变量assert关闭此语句。-O`-OO`PYTHONOPTIMIZE

值 1:

  • 断言被禁用;

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

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

  • 并且,__debug__设置为False

值 2:禁用更多内容

  • 文档字符串被禁用;

因此,使用该assert语句来验证某种预期数据是非常危险的,甚至可能存在一些安全问题。然后,如果您需要验证某些权限,我建议您raise AuthError改为这样做。作为有效的先决条件,assert程序员通常将其用于没有用户直接交互的库或模块。

解决方案 13:

如果断言后的语句为真,程序将继续,但如果断言后的语句为假,程序就会出错。就这么简单。

例如:

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

解决方案 14:

在 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

解决方案 15:

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

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

解决方案 16:

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

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

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

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

希望有帮助:)

解决方案 17:

我的简短解释是:

  • assert如果表达式为假,则引发AssertionError,否则继续执行代码,如果有逗号,无论它是什么,它都会是AssertionError: whatever after comma,代码如下:raise AssertionError(whatever after comma)

关于此的相关教程:

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

解决方案 18:

正如其他答案中所写的,assert语句用于检查给定点的程序状态。

-O我不会重复关于关联消息、括号或选项和常量的内容__debug__。另请查看文档以获取第一手资料。我将重点讨论您的问题: 有什么用assert?更准确地说,什么时候(以及什么时候不应该)应该使用assert

这些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的启发
。您无法使用该语句完全模拟契约式编程,但保留意图很有趣。assert

下面是一个例子。假设你必须编写一个head函数(比如 [ headHaskell 中的函数](
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。这很重要,因为AssertionError不是任何运行时错误:它表示违反规范。我想要一个警告,但我得到了一个错误。幸运的是,我可以禁用检查(使用选项-O),但风险自负。我会这样做,因为崩溃确实很昂贵,并希望得到最好的结果。想象一下,我的程序嵌入在穿越黑洞的宇宙飞船中。我将禁用断言并希望程序足够强大,尽可能长时间不崩溃。

此示例仅涉及先决条件,但您可以使用它assert来检查后置条件(返回值和/或状态)和不变量(类的状态)。请注意,使用检查后置条件和不变量assert可能很麻烦:

  • 对于后置条件,您需要将返回值分配给一个变量,如果您正在处理方法,则可能需要存储对象的初始状态;

  • 对于不变量,您必须检查方法调用之前和之后的状态。

你不会拥有像 Eiffel 那样复杂的东西,但是你却可以提高程序的整体质量。


总而言之,语句是一种检测不应发生assert情况的便捷方法。违反规范(例如将空列表传递给)是第一类不应发生的情况。因此,虽然语句可用于检测任何意外情况,但它是确保满足规范的一种特权方法。一旦您将语句插入到代码中以表示规范,我们希望您已经提高了程序的质量,因为将报告不正确的参数、不正确的返回值、不正确的类状态……。head`assert`assert

解决方案 19:

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

语法: assert <condition>assert <condition>,<error message>

它有一个条件/表达式,该条件/表达式应该始终为真。如果条件为假,则语句assert将停止程序并抛出一条错误消息AssertionError。因此,您的断言表达式将是您不希望在程序中出现的内容。

例如

  1. assert <condition>-- 使用不带断言<error message>

var = int(input("Enter value 1-9 inclusive:"))                                 
assert var!=0 
print(var)

输出 :

如果输入为 0:

AssertionError

如果输入为 1:

1
  1. assert <condition>,<error message>-- 使用断言<error message>

var = int(input("Enter value 1-9 inclusive:"))                                 
assert var!=0,"Input cannot be zero"
print(var)

输出 :

如果输入为 0:

AssertionError: Input cannot be zero

如果输入为 1:

1

要点:

  1. 它被用作调试工具。

  2. 它需要一个表达式和一个可选的消息。

  3. 它存在于几乎每种编程语言中

解决方案 20:

Python 中的关键字如果关键字后面的代码为,assert则引发。 如果不是,则继续执行,就像什么都没有发生一样。AssertionError`assert`False

例1

a = 5
b = 6

assert a == b

输出:

AssertionError

这是因为,显然,a不等于b。如果您想Exception在代码中引发,这尤其有用。

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

上面的例子实际上是没用的,但请记住,它主要用于调试目的,这样您就可以追踪您的错误。

解决方案 21:

格式:assert Expression[,arguments] 当 assert 遇到语句时,Python 会评估该表达式。如果语句不为真,则会引发异常(assertionError)。如果断言失败,Python 将使用 ArgumentExpression 作为 AssertionError 的参数。AssertionError 异常可以像任何其他异常一样使用 try-except 语句进行捕获和处理,但如果不处理,它们将终止程序并产生回溯。示例:

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!    

解决方案 22:

def getUser(self, id, Email):

    user_key = id and id or Email

    assert user_key

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

解决方案 23:

>>>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
>>> 
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1120  
  IPD(Integrated Product Development,集成产品开发)流程是一种广泛应用于高科技和制造业的产品开发方法论。它通过跨职能团队的紧密协作,将产品开发周期缩短,同时提高产品质量和市场成功率。在IPD流程中,CDCP(Concept Decision Checkpoint,概念决策检查点)是一个关...
IPD培训课程   75  
  研发IPD(集成产品开发)流程作为一种系统化的产品开发方法,已经在许多行业中得到广泛应用。它不仅能够提升产品开发的效率和质量,还能够通过优化流程和资源分配,显著提高客户满意度。客户满意度是企业长期成功的关键因素之一,而IPD流程通过其独特的结构和机制,能够确保产品从概念到市场交付的每个环节都围绕客户需求展开。本文将深入...
IPD流程   66  
  IPD(Integrated Product Development,集成产品开发)流程是一种以跨职能团队协作为核心的产品开发方法,旨在通过优化资源分配、提高沟通效率以及减少返工,从而缩短项目周期并提升产品质量。随着企业对产品上市速度的要求越来越高,IPD流程的应用价值愈发凸显。通过整合产品开发过程中的各个环节,IPD...
IPD项目管理咨询   76  
  跨部门沟通是企业运营中不可或缺的一环,尤其在复杂的产品开发过程中,不同部门之间的协作效率直接影响项目的成败。集成产品开发(IPD)作为一种系统化的项目管理方法,旨在通过优化流程和增强团队协作来提升产品开发的效率和质量。然而,跨部门沟通的复杂性往往成为IPD实施中的一大挑战。部门之间的目标差异、信息不对称以及沟通渠道不畅...
IPD是什么意思   70  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用