Для полного объяснения рассмотрим следующий пример:
>>> 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
или False
, ответ прост. В противном случае интерпретатор пытается выяснить, является ли объект правдой по телефону PyObject_IsTrue()
, который определен в object protocol. code in object.c точно показывает, как это работает:
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
также считается ложным.Затем проверяются различные протоколы, такие как number protocol, mapping protocol и sequence protocol. В противном случае объект считается истинным.
Для его обертывания: x
считается истинным, если он равен True
, истинным в соответствии с номером, протоколом сопоставления или последовательности или каким-либо другим видом объекта. Если вы хотите, чтобы ваш объект оценивал значение false, вы можете сделать это, выполнив любой из указанных протоколов, см. Предоставленные ссылки.
По сравнению с None
, как в if x is None
, это явное сравнение. Приведенная выше логика не применяется.
Примечание: в настоящее время [ 'если:' эквивалентно 'если это .has_children():'] (Http: //hg.python .org/cpython/file/43f27e69bc29/Lib/xml/etree/ElementTree.py # l231), который сильно отличается от 'if не None:'. –
jfs