Hi, Habr. In anticipation of the start of the course “Python Developer. Professional ” prepared a traditional translation of useful material.
We also invite everyone to visit the open webinar on "Data visualization with matplotlib".
:
not True, False, False .
, ? , «» «», , , .
( , , « », , )
not
, , not
– UNARY_NOT.
not a
:
>>> import dis
>>> def spam(): not a
...
>>> dis.dis(spam)
1 0 LOAD_GLOBAL 0 (a)
2 UNARY_NOT
4 POP_TOP
6 LOAD_CONST 0 (None)
8 RETURN_VALUE
UNARY_NOT , PyObject_IsTrue()
: True False, False True.
case TARGET(UNARY_NOT): {
PyObject *value = TOP();
int err = PyObject_IsTrue(value);
Py_DECREF(value);
if (err == 0) {
Py_INCREF(Py_True);
SET_TOP(Py_True);
DISPATCH();
}
else if (err > 0) {
Py_INCREF(Py_False);
SET_TOP(Py_False);
DISPATCH();
}
STACK_SHRINK(1);
goto error;
}
, True
not
, True. PyObject_IsTrue()
, , .
/* Test a value used as condition, e.g., in a for or if statement.
Return -1 if an error occurred */
int
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, True
False, False
None, False
,
bool
, ,bool
(,nb_bool
)
len()
(,mp_length
sq_length
):
0, True
False
, True
1-3 6 , 4 5 .
bool
/ bool , « » True, False.
len()
len()
, . sq_length
( ) mp_length
( /).
, , .
len
– / len
. , « , >= 0». , «» int
, , « »… « ». ?
index
« », / index
. , PyNumber_Index()
. , , :
int
,
index
index
int
, ( , ).
TypeError
.
Python operator.index()
. , PyNumber_Index()
, not
len
, . , :
PyNumber_Index()
Python:
def index(obj: Object, /) -> int:
"""Losslessly convert an object to an integer object.
If obj is an instance of int, return it directly. Otherwise call __index__()
and require it be a direct instance of int (raising TypeError if it isn't).
"""
# https://github.com/python/cpython/blob/v3.8.3/Objects/abstract.c#L1260-L1302
if isinstance(obj, int):
return obj
length_type = builtins.type(obj)
try:
__index__ = _mro_getattr(length_type, "__index__")
except AttributeError:
msg = (
f"{length_type!r} cannot be interpreted as an integer "
"(must be either a subclass of 'int' or have an __index__() method)"
)
raise TypeError(msg)
index = __index__(obj)
# Returning a subclass of int is deprecated in CPython.
if index.__class__ is int:
return index
else:
raise TypeError(
f"the __index__() method of {length_type!r} returned an object of "
f"type {builtins.type(index).__name__!r}, not 'int'"
)
len()
len()
: int
. , , index()
len()
, PyLong_FromSsize_t()
, int
.
len()
, len()
index ()
, , int
, 0 .. , len()
:
def len(obj: Object, /) -> int:
"""Return the number of items in a container."""
# https://github.com/python/cpython/blob/v3.8.3/Python/bltinmodule.c#L1536-L1557
# https://github.com/python/cpython/blob/v3.8.3/Objects/abstract.c#L45-L63
# https://github.com/python/cpython/blob/v3.8.3/Objects/typeobject.c#L6184-L6209
type_ = builtins.type(obj)
try:
__len__ = _mro_getattr(type_, "__len__")
except AttributeError:
raise TypeError(f"type {type!r} does not have a __len__() method")
length = __len__(obj)
# Due to len() using PyObject_Size() (which returns Py_ssize_t),
# the returned value is always a direct instance of int via
# PyLong_FromSsize_t().
index = int(_index(length))
if index < 0:
raise ValueError("__len__() should return >= 0")
else:
return index
operator.truth()
not, not
– not not
. , , , , , .
Python . bool()
( bool.new()
), , , , operator.truth()
. , , PyObject_IsTrue()
. slot_nb_bool ()
, , , PyObject_IsTrue()
. , PyObject_IsTrue()
, , .
, , operator.truth()
( bool
, , True False , 1 0 Python).
operator.truth()
:
def truth(obj: Any, /) -> bool:
"""Return True if the object is true, False otherwise.
Analogous to calling bool().
"""
if obj is True:
return True
elif obj is False:
return False
elif obj is None:
return False
obj_type = type(obj)
try:
__bool__ = debuiltins._mro_getattr(obj_type, "__bool__")
except AttributeError:
# Only try calling len() if it makes sense.
try:
__len__ = debuiltins._mro_getattr(obj_type, "__len__")
except AttributeError:
# If all else fails...
return True
else:
return True if debuiltins.len(obj) > 0 else False
else:
boolean = __bool__(obj)
if isinstance(boolean, bool):
# Coerce into True or False.
return truth(boolean)
else:
raise TypeError(
f"expected a 'bool' from {obj_type.__name__}.__bool__(), "
f"not {type(boolean).__name__!r}"
)
not
operator.truth()
, operator.not_()
– :
lambda a, /: False if truth(a) else True
, , , .
, desugar.
«Python Developer. Professional».