断言是什么意思?它是如何使用的?
当前回答
正如其他答案所指出的,assert类似于在给定条件不为真时抛出异常。一个重要的区别是,如果使用优化选项-O编译代码,断言语句将被忽略。文档说断言表达式可以更好地描述为等效于
if __debug__:
if not expression: raise AssertionError
如果你想彻底测试你的代码,然后在你高兴地看到你的断言案例都没有失败时发布一个优化版本,这可能是有用的——当优化打开时,__debug__变量变成False,条件将停止计算。如果您依赖断言,而没有意识到断言已经消失,该特性还可以发现这一点。
其他回答
如果你想知道python中保留函数的确切功能,输入help(enter_keyword)
如果您正在输入保留关键字,请确保将其输入为字符串。
正如其他答案所指出的,assert类似于在给定条件不为真时抛出异常。一个重要的区别是,如果使用优化选项-O编译代码,断言语句将被忽略。文档说断言表达式可以更好地描述为等效于
if __debug__:
if not expression: raise AssertionError
如果你想彻底测试你的代码,然后在你高兴地看到你的断言案例都没有失败时发布一个优化版本,这可能是有用的——当优化打开时,__debug__变量变成False,条件将停止计算。如果您依赖断言,而没有意识到断言已经消失,该特性还可以发现这一点。
断言是什么意思?它是如何使用的?
这里有很好的答案,但不是问题的第二部分。尽管有多年的实践经验,但我直到最近才明白断言的目的。
其他人已经解释了如何使用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关闭它。
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通常由程序员在不与用户直接交互的库或模块上使用。
在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
推荐文章
- Numpy Max vs amax vs maximum
- 我应该在.gitignore文件中添加Django迁移文件吗?
- 每n行有熊猫
- 实例属性attribute_name定义在__init__之外
- 如何获取在Python中捕获的异常的名称?
- 第一次出现的值大于现有值的Numpy
- 如何从Python函数中返回两个值?
- 前一个月的Python日期
- Python中方括号括起来的列表和圆括号括起来的列表有什么区别?
- Python日志记录不输出任何东西
- 每n秒运行特定代码
- SQLAlchemy是否有与Django的get_or_create等价的函数?
- 如何将python datetime转换为字符串,具有可读格式的日期?
- 美丽的汤和提取div及其内容的ID
- 断言是邪恶的吗?