Why does passing a list to the following format method fail, but passing the same list, coerced to a tuple run without errors?
From my test, the tuple is not (multiply) inheriting from Python's atomic numeric types (I assume not complex either) so overall I'm confused by what the interpreter is telling me, and why it can seemingly happily treat my tuple as containing values to format but not of my (ceteris paribus) list.
#!/usr/bin/env python3
import math
from multiprocessing import Pool
def func(x):
return math.sin(x)
if __name__ == "__main__":
with Pool(5) as p:
x = p.map(func, range(1, 4))
x_tuple = tuple(x)
try:
print(", ".join([r"/"] * len(x)) % x)
print(f"Print with list succeeded")
except Exception as e:
print(f"Print with list fails: {e}")
try:
print(", ".join([r"/"] * len(x_tuple)) % x_tuple)
print(f"Print with tuple succeeded")
except:
print(f"Print with tuple fails: {e}")
print(f"{isinstance(x, float) = }")
print(f"{isinstance(x, int) = }")
The above gives the following output:
Print with list fails: must be real number, not list
0.841471, 0.909297, 0.141120
Print with tuple succeeded
isinstance(x, float) = False
isinstance(x, int) = False
CodePudding user response:
This is just how format % values
works; as documented in the manual:
If format requires a single argument, values may be a single non-tuple object. Otherwise, values must be a tuple with exactly the number of items specified by the format string, or a single mapping object (for example, a dictionary).
(See: printf
-style String Formatting)
The reason it's done this way is to support simplified forms with just one value; things like "Hello %s" % name
; when you use a list, it interprets that as being the simplified form; "Hello %s" % x
would also work that way, formatting up the whole list using %s
. However, a whole list can't be formatted up using %f
, and if it could be, there would be no values for the remaining %f
specifiers.