有关完整说明,请考虑以下示例:
>>> import dis
>>> def is_truthy(x):
>>> return "Those sweed words!" if x else "All lies!"
>>> is_truthy(None)
'All lies!'
>>> is_truthy(1)
'Those sweed words!'
>>> is_truthy([])
'All lies!'
>>> is_truthy(object())
'Those sweed words!'
发生了is_truthy()
什么?让我们来了解一下。跑步dis.dis(is_truthy)
给你:
2 0 LOAD_FAST 0 (x)
3 POP_JUMP_IF_FALSE 10
6 LOAD_CONST 1 ('The pure word')
9 RETURN_VALUE
>> 10 LOAD_CONST 2 ('All lies!')
13 RETURN_VALUE
如您所见x
,被压入堆栈,然后POP_JUMP_IF_FALSE
被执行。这将跳转到第一次推送,然后返回正确答案。
POP_JUMP_IF_FALSE
在ceval.c中定义:
TARGET(POP_JUMP_IF_FALSE) {
PyObject *cond = POP();
int err;
if (cond == Py_True) {
Py_DECREF(cond);
FAST_DISPATCH();
}
if (cond == Py_False) {
Py_DECREF(cond);
JUMPTO(oparg);
FAST_DISPATCH();
}
err = PyObject_IsTrue(cond);
Py_DECREF(cond);
if (err > 0)
err = 0;
else if (err == 0)
JUMPTO(oparg);
else
goto error;
DISPATCH();
如您所见,如果所使用的对象POP_JUMP_IF_FALSE
已经是True
or False
,则答案很简单。否则,解释器试图通过调用对象协议中定义的方法来确定对象是否真实。object.c中的代码向您展示了它是如何工作的:PyObject_IsTrue()
PyObject_IsTrue(PyObject *v)
{
Py_ssize_t res;
if (v == Py_True)
return 1;
if (v == Py_False)
return 0;
if (v == Py_None)
return 0;
else if (v->ob_type->tp_as_number != NULL &&
v->ob_type->tp_as_number->nb_bool != NULL)
res = (*v->ob_type->tp_as_number->nb_bool)(v);
else if (v->ob_type->tp_as_mapping != NULL &&
v->ob_type->tp_as_mapping->mp_length != NULL)
res = (*v->ob_type->tp_as_mapping->mp_length)(v);
else if (v->ob_type->tp_as_sequence != NULL &&
v->ob_type->tp_as_sequence->sq_length != NULL)
res = (*v->ob_type->tp_as_sequence->sq_length)(v);
else
return 1;
/* if it is negative, it should be either -1 or -2 */
return (res > 0) ? 1 : Py_SAFE_DOWNCAST(res, Py_ssize_t, int);
}
同样,如果对象只是True
或False
他们自己,答案很简单。None
也被认为是假的。然后检查数字协议、映射协议和序列协议等各种协议。否则该对象被认为是真实的。
总结一下:x
如果是则被认为是True
真,根据数字、映射或序列协议或其他某种对象为真。如果您希望您的对象评估为假,您可以通过实现任何上述协议来实现,请参阅提供的链接。
与None
like inif x is None
进行比较是显式比较。上述逻辑不适用。