f-string syntax deficiency?

Mark Bourne nntp.mbourne at spamgourmet.com
Tue Jun 6 15:46:38 EDT 2023


Roel Schroeven wrote:
> Op 6/06/2023 om 16:08 schreef Chris Angelico:
>> On Wed, 7 Jun 2023 at 00:06, Neal Becker <ndbecker2 at gmail.com> wrote:
>> >
>> > The following f-string does not parse and gives syntax error on 3.11.3:
>> >
>> > f'thruput/{"user" if opt.return else "cell"} vs. elevation\n'
>> >
>> > However this expression, which is similar does parse correctly:
>> >
>> > f'thruput/{"user" if True else "cell"} vs. elevation\n'
>> >
>> > I don't see any workaround.  Parenthesizing doesn't help:
>> >  f'thruput/{"user" if (opt.return) else "cell"} vs. elevation\n'
>> >
>> > also gives a syntax error
>>
>> Is this a problem with the f-string, or with the expression
>> opt.return? That's a keyword.
> 'return' being a keyowrd is definitely going to be the problem.
> 
> Neal, I assume you're using 'opt.return' also outside of that f-string. 
> Does that work? How did you manage to do that? I tried to make a simple 
> class with an attribute called 'return', but that already fails with a 
> syntax error.

Just for fun, here's a class which has any attribute you like, including 
`return`:
```
class AnyAttr:
     def __getattr__(self, name):
         return f'This is the value of the <{name}> attribute'
```

The usual "dot" notation to access the attributes works for arbitrary 
attributes, but not for `return` because, as mentioned, that's a keyword:
```
 >>> aa = AnyAttr()
 >>> aa.myattribute
'This is the value of the <myattribute> attribute'
 >>> aa.random
'This is the value of the <random> attribute'
 >>> aa.return
   File "<stdin>", line 1
     aa.return
        ^
SyntaxError: invalid syntax
```

If you really do have an instance with a `return` attribute (perhaps 
because it does fun things with `__getattr__`), you can access it if 
necessary using `getattr`:
```
 >>> getattr(aa, 'return')
'This is the value of the <return> attribute'
```

You can even access attributes with spaces and other usually-invalid 
characters:
```
 >>> getattr(aa, 'This really is an attribute name!')
'This is the value of the <This really is an attribute name!> attribute'
```

Using `getattr` to access the value, Neal's f-string can be made to work:
```
 >>> f'thruput/{"user" if getattr(aa, "return") else "cell"} vs. 
elevation\n'
'thruput/user vs. elevation\n'
```

But if you have control over the implementation of that `opt` object, 
it's probably better to give the attribute a different name which is a 
valid identifier.  PEP-8 suggests a convention of using a single 
trailing underscore (e.g. `return_`) to avoid conflicts with keywords, 
if there's no better name.

Perhaps `opt` is the arguments returned by `argparse.ArgumentParser` and 
you want the command-line option to be `--return`.  In that case, see 
the `dest` argument to `add_argument()` which can specify a different 
name for the attribute used in code (it's almost like they thought about 
this type of problem ;o)).  If it's from `optparse`, that has a similar 
argument, but `optparse` is deprecated so consider updating to `argparse`.

> 
> (Recently there has been an effort to provide clearer and more useful 
> error messages; this seems to be a case where there is still room for 
> improvement: "SyntaxError: invalid syntax" doesn't immediately remind me 
> of that fact that 'return' is a keyword and therefor can't be used as an 
> attribute.)

-- 
Mark.


More information about the Python-list mailing list