
On 7/21/2015 1:16 AM, Stephen J. Turnbull wrote:
Eric V. Smith writes:
instead of trying to figure out that the numeric-looking '0' gets converted to an integer, and the non-numeric-looking 'c' gets left as a string. That logic already exists in str.format(), so let's just leverage it from there.
Yes, please! Guido's point that he wants no explicit use of locals(), etc, in the implementation took me a bit of thought to understand, but then I realized that it means a "macro" transformation with the resulting expression evaluated in the same environment as an explicit .format() would be. And that indeed makes the whole thing as explicit as invoking str.format would be.
Right. That is indeed the beauty of the thing. I now think locals(), etc. is a non-starter.
I don't *really* care what transformations are used to get that result, but DRYing this out and letting the __format__ method of the indexed object figure out the meaning of the format string makes me feel better about my ability to *think* about the meaning of an f"..." string.
In particular, isn't it possible that a user class's __format__ might decide that *all* keys are strings? I don't see how the transformation Steve Dower proposed can possibly deal with that ambiguity.
In today's world: '{a[0]:4d}'.format(a=a) the object who's __format__() method is being called is a[0], not a. So it's not up to the object to decide what the keys mean. That decision is being made by the ''.format() implementation. And that's also the way I'm envisioning it with f-strings.
Another conundrum is that it's not obvious whether f"{a[01]}" is a SyntaxError (as it is with str.format) or equivalent to "{}".format(a['01']) (as my hypothetical user's class would expect).
It would still be a syntax error, in my imagined implementation, because it's really calling ''.format() to do the expansion. So here's what I'm thinking f'some-string' would expand to. As you note above, it's happening in the caller's context: new_fmt = remove_all_object_names_from_string(s) objs = find_all_objects_referenced_in_string(s) result = new_fmt.format(*objs) So given: X = namedtuple('X', 'name width') a = X('Eric', 10) value = 'some value' then: f'{a.name:*^{a.width}}:{value}' would become this transformed code: '{.name:*^{.width}}:{}'.format(*[a, a, value]) which would evaluate to: '***Eric***:some value' The transformation of the f-string to new_fmt and the computation of objs is the only new part. The transformed code above works today. Eric.