I’m not entirely sure. Are there any situations in which (a and b) and c is not the same as (a and b and c)? The disassembly of both looks identical. Or is it something that can happen with mixed and and or operators that means it’s better to group all the ands and all the ors?

At least in pyparsing, a left-associative rule generates a list of tokens like [test1, test2, test3] while a right-associative rule generates [test1, [test2, test3]]. It’s more work to create and implement short-circuiting on a left-associative binary tree than on a list.

I think the mathematical properties of BoolOpor and and, and BinOp| and & are identical, so there is no reason why you’d implement things one way or the other. The ast module seems to be built by many different people (essentially every time new syntax is added IIRC) over a long time so inconsistencies are to be expected.

produce different bytecodes. The truth value of a is always evaluated once in the former case, but can be evaluated two times in the latter case.

Boolean expressions in boolean context are optimized. Both

if a and b and c: x

and

if (a and b) and c: x

produce the same bytecode. The truth value of a is always evaluated once.

This is an implementation detail, and you code should not rely on it.

Other than this, the difference between multi-argument BoolOp and nested two-argument BoolOp is that the former uses iteration, and the latter uses recursion. The recursion level is limited (otherwise it can cause stack overflow), this limits the number of sequential and’s and or’s, the same way as the number of sequential arithmetic operators is currently limited.