% will spew TypeErrors if you don't get the format specifier right.
To be honest, to me the "%" seems the most pythonic way to do it. Format does not seem easier to understand to me . String formatting just cannot be transformed to natural language. I at least don't think "I need to format this string", I think "this variable needs to be in there", in the in there might as well be called "%". I think ["a is %s" % a for a in all_as] just fits.
Although named parameters are nicer with format. In no way should there be a third way to do it. Isn't that the basic principle of Python, to care about things like this? I mean this whole Python 3 problem was to a small extend caused by people rather having an incompatible syntax than two ways to print a string. Going through these troubles and then inflating the language with new syntax for the same thing seems like a waste.
1: https://en.wikipedia.org/wiki/History_of_Python#Version_2.0
2: And for my money, significantly more confusing (and less powerful) than something like Perl's `map`.
String concatenation has one use-case where it is the obvious way, too, namely when you have to concatenate already existing strings without modification, since "%s%s" % (a, b) is just stupid, beyond that you would use string formatting.
Maybe there are unique obvious use-cases for the different formatting options as well, but I don't know them. I give you, that "%" is bad for named arguments, but why wouldn't you just improve that then? I think they do the exact same thing and are good for the exact same contexts. If somebody knows more than me, I would be very happy to be proven wrong.
Perhaps they should. I'm not making a case specifically for the proposed strategy (interpolation), just that if they are going to implement it, that it took this long is odd, and somewhat laughable. Personally, I think the named string format is superior to this new feature in many respects except the most simplistic of cases, but I don't often write python, so my opinion may be colored by that.
Yes. Additionally, I prefer the clear directionality of control and transform denoted by the dual capabilities of `map` and `grep` over list comprehensions, especially when chaining. Even better, IMO, is Perl 6's ability to use the feed operator to go left-to-right, so if the map block can be read the same direction as the flow of list items.[1] Having to scan back and forth to determine what is happening is a real detriment to the readability of these types of expressions, IMO.
> I don't see how list comprehensions are less powerful, though.
You're correct. Not strictly less powerful, just that the single expression for transforming the item may require multiple comprehensions where a single slightly more complex map block could get away with a temporary variable. Given that I dislike the way multiple list comprehensions read, this may be a bigger deal for me than most.
1: E.g. my @new = ( @original ==> grep { ... } ==> map { ... } ==> sort { ... } );
original.filter(...).map(...).sort(), which in python would be `sorted([... for x in original if ...], ...)`.
I'll agree that sometimes the functional/chainable approach is nicer, but often it also isn't necessary
Yes, a method chaining format (such as Ruby and JS, and which can be enabled with a module in Perl) does approximate the control flow I'm referring to, The only different to the feed operator in Perl 6 is that the feed works on a per-item basis, allowing the list to be lazily generated, which also means it's a closer approximation to how you would code it in a for loop, as statements are done in succession on each item.
E.g.
my @source = 1..Inf;
my @elevensies = ( @source ==> map { $_*11 } );
my @odd-elevensies = ( @elevensies ==> grep *%2 );
my @root-of-odd-elevensies = ( @odd-elevensies ==> map *.sqrt );
Although in this case the left feed operator may be clearer.> which in python would be `sorted([... for x in original if ...], ...)`.
> I'll agree that sometimes the functional/chainable approach is nicer, but often it also isn't necessary
Well, the example I gave was simplistic and to show direction. A more complex example would require a comprehension of a comprehension, which is where I start to have real issues with the format, and which is not represented from that example, which wasn't meant to illustrate that particular problem.
source = count(1)
elevensies = (x * 11 for x in source)
odd_elevensies = (x for x in elevensies if x%2)
root_of_odd_elevensies = (math.sqrt(x) for x in odd_elevensies)
To me, the examples seem fairly equivalent, with the exception that Python's is, in my opinion, more readable for a newbie, since it doesn't require knowing map() or grep() - just for loops and ifs.I agree list comprehensions in the simple form are easier for a newbie to recognize, but I also like the way map and filter make you think about your actions, and think they are clearer in the less trivial cases (as I mentioned above). I say "filter" because while I am completely familiar with that terminology, I accept that it's an unneeded departure from the common terminology for that task.