Overview
Booleans in Python are implemented as a subclass of integers. There are only two boolean objects: Py_True and Py_False. Both are immortal (never deallocated).
Type Object
PyBool_Type
The Python bool type object.
Type Checking
PyBool_Check
int PyBool_Check (PyObject * o )
Check if object is a boolean (True or False).
Returns: 1 if boolean, 0 otherwise (never fails)
Example:
if ( PyBool_Check (obj)) {
if (obj == Py_True) {
printf ( "True \n " );
} else {
printf ( "False \n " );
}
}
Boolean Singletons
Py_True
The Python True object. This object is immortal and has no methods.
Example:
return Py_True; // No need to Py_INCREF (but doesn't hurt)
Py_False
The Python False object. This object is immortal and has no methods.
Example:
return Py_False; // No need to Py_INCREF (but doesn't hurt)
Since Python 3.12, Py_True and Py_False are immortal. You don’t need to increment their reference counts, but it’s still good practice to do so for compatibility.
Testing Truth Values
Py_IsTrue
int Py_IsTrue (PyObject * x )
Test if object is the True singleton. Equivalent to x is True in Python.
Returns: 1 if True, 0 otherwise
Example:
if ( Py_IsTrue (obj)) {
// obj is exactly True
}
Py_IsFalse
int Py_IsFalse (PyObject * x )
Test if object is the False singleton. Equivalent to x is False in Python.
Returns: 1 if False, 0 otherwise
Example:
if ( Py_IsFalse (obj)) {
// obj is exactly False
}
Creating Booleans
PyBool_FromLong
PyObject * PyBool_FromLong ( long v )
Return Py_True or Py_False based on truth value of integer.
Returns: Py_True if v is non-zero, Py_False if zero
Example:
long status = check_condition ();
return PyBool_FromLong (status); // Returns True if status != 0
Common usage:
int is_valid = validate_input (data);
return PyBool_FromLong (is_valid);
Return Macros
Py_RETURN_TRUE
Convenience macro to return Py_True from a function.
Example:
static PyObject * is_ready (MyObject * self , PyObject * Py_UNUSED (ignored)) {
if ( self -> ready )
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
Py_RETURN_FALSE
Convenience macro to return Py_False from a function.
Expands to:
// Python 3.12+:
return Py_True; // or Py_False
// Python 3.11 and earlier:
return Py_NewRef (Py_True); // Increments refcount
Complete Example
#define PY_SSIZE_T_CLEAN
#include <Python.h>
static PyObject * check_even (PyObject * self , PyObject * args ) {
long number;
if ( ! PyArg_ParseTuple (args, "l" , & number))
return NULL ;
// Method 1: Using macro
if (number % 2 == 0 )
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
static PyObject * check_positive (PyObject * self , PyObject * args ) {
long number;
if ( ! PyArg_ParseTuple (args, "l" , & number))
return NULL ;
// Method 2: Using PyBool_FromLong
return PyBool_FromLong (number > 0 );
}
static PyObject * check_flags (PyObject * self , PyObject * args ) {
PyObject * flag1, * flag2;
if ( ! PyArg_ParseTuple (args, "OO" , & flag1, & flag2))
return NULL ;
// Check if both are True
if ( Py_IsTrue (flag1) && Py_IsTrue (flag2))
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
static PyMethodDef module_methods [] = {
{ "check_even" , check_even, METH_VARARGS,
"Check if number is even" },
{ "check_positive" , check_positive, METH_VARARGS,
"Check if number is positive" },
{ "check_flags" , check_flags, METH_VARARGS,
"Check if both flags are True" },
{ NULL , NULL , 0 , NULL }
};
static struct PyModuleDef boolmodule = {
PyModuleDef_HEAD_INIT,
"boolexample" ,
"Boolean operations example" ,
- 1 ,
module_methods
};
PyMODINIT_FUNC PyInit_boolexample ( void ) {
return PyModule_Create ( & boolmodule);
}
Working with Boolean Values
Converting to C bool
// Test if object is truthy
int is_true = PyObject_IsTrue (obj);
if (is_true < 0 ) {
// Error occurred
return NULL ;
}
if (is_true) {
// Object is truthy
}
Boolean Operations
static PyObject * logical_and (PyObject * self , PyObject * args ) {
PyObject * a, * b;
int result_a, result_b;
if ( ! PyArg_ParseTuple (args, "OO" , & a, & b))
return NULL ;
result_a = PyObject_IsTrue (a);
if (result_a < 0 )
return NULL ;
if ( ! result_a)
Py_RETURN_FALSE;
result_b = PyObject_IsTrue (b);
if (result_b < 0 )
return NULL ;
return PyBool_FromLong (result_b);
}
Comparison with None
if ( Py_IsTrue (obj)) {
// obj is True
} else if ( Py_IsFalse (obj)) {
// obj is False
} else if ( Py_IsNone (obj)) {
// obj is None
} else {
// obj is some other object
}
Truth Value Testing
For general truth value testing (not just bool objects), use:
int PyObject_IsTrue (PyObject * o ); // Returns 1, 0, or -1 on error
int PyObject_Not (PyObject * o ); // Returns negation
Example:
static PyObject * negate (PyObject * self , PyObject * arg ) {
int negated = PyObject_Not (arg);
if (negated < 0 )
return NULL ; // Error in truth value testing
return PyBool_FromLong (negated);
}
Best Practices
Use macros for simple returns: if (condition)
Py_RETURN_TRUE;
Py_RETURN_FALSE;
Use PyBool_FromLong for computed results: return PyBool_FromLong (x > 0 && x < 10 );
Don’t compare by reference unless needed: // For identity check:
if (obj == Py_True) { ... }
// For truth value:
int is_true = PyObject_IsTrue (obj);
Don’t create new boolean objects: // WRONG: Don't try to create booleans
PyObject * mybool = PyObject_Call ( & PyBool_Type , ...);
// RIGHT: Use the singletons
return Py_True;
return PyBool_FromLong (value);
See Also
Integer Objects Booleans are a subclass of int
Object Protocol Truth value testing
Reference Counting Immortal objects