I was trying to print a truth table for Boolean expressions. While doing this, I stumbled upon the following:
>>> format(True, "") # shows True in a string representation, same as str(True) 'True' >>> format(True, "^") # centers True in the middle of the output string '1'
As soon as I specify a format specifier, format()
converts True
to 1
. I know that bool
is a subclass of int
, so that True
evaluates to 1
:
>>> format(True, "d") # shows True in a decimal format '1'
But why does using the format specifier change 'True'
to 1
in the first example?
I turned to the docs for clarification. The only thing it says is:
A general convention is that an empty format string (
""
) produces the same result as if you had calledstr()
on the value. A non-empty format string typically modifies the result.
So the string gets modified when you use a format specifier. But why the change from True
to 1
if only an alignment operator (e.g. ^
) is specified?
Use the built-in bool() method to print the value of a variable.
You can convert True and False to strings 'True' and 'False' with str() . Non-empty strings are considered True , so if you convert False to strings with str() and then back to bool type with bool() , it will be True .
bool() in Python. Python bool() function is used to return or convert a value to a Boolean value i.e., True or False, using the standard truth testing procedure.
Excellent question! I believe I have the answer. This requires digging around through the Python source code in C, so bear with me.
First, format(obj, format_spec)
is just syntactic sugar for obj.__format__(format_spec)
. For specifically where this occurs, you'd have to look in abstract.c, in the function:
PyObject * PyObject_Format(PyObject* obj, PyObject *format_spec) { PyObject *empty = NULL; PyObject *result = NULL; ... if (PyInstance_Check(obj)) { /* We're an instance of a classic class */ HERE -> PyObject *bound_method = PyObject_GetAttrString(obj, "__format__"); if (bound_method != NULL) { result = PyObject_CallFunctionObjArgs(bound_method, format_spec, NULL); ... }
To find the exact call, we have to look in intobject.c:
static PyObject * int__format__(PyObject *self, PyObject *args) { PyObject *format_spec; ... return _PyInt_FormatAdvanced(self, ^ PyBytes_AS_STRING(format_spec), | PyBytes_GET_SIZE(format_spec)); LET'S FIND THIS ... }
_PyInt_FormatAdvanced
is actually defined as a macro in formatter_string.c as a function found in formatter.h:
static PyObject* format_int_or_long(PyObject* obj, STRINGLIB_CHAR *format_spec, Py_ssize_t format_spec_len, IntOrLongToString tostring) { PyObject *result = NULL; PyObject *tmp = NULL; InternalFormatSpec format; /* check for the special case of zero length format spec, make it equivalent to str(obj) */ if (format_spec_len == 0) { result = STRINGLIB_TOSTR(obj); <- EXPLICIT CAST ALERT! goto done; } ... // Otherwise, format the object as if it were an integer }
And therein lies your answer. A simple check for whether format_spec_len
is 0
, and if it is, convert obj
into a string. As you well know, str(True)
is 'True'
, and the mystery is over!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With