Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printing boolean values True/False with the format() method in Python

Tags:

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 called str() 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?

like image 508
Stefan van den Akker Avatar asked May 14 '14 12:05

Stefan van den Akker


People also ask

How do you print a boolean value in Python?

Use the built-in bool() method to print the value of a variable.

How do you convert true to boolean true in Python?

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 .

How do I return true and false in Python?

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.


1 Answers

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!

like image 181
huu Avatar answered Sep 29 '22 18:09

huu