5

In Python strings have a method lower():

>>> dir('A')
[... 'ljust', 'lower', 'lstrip', ...]

However, when one tries '{0.lower()}'.format('A'), the response states:

>>> '{0.lower()}'.format('A')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'lower()'

Can someone help me understand why the line above throws an AttributeError in this case? This seems like it should not be an AttributeError, though I must be mistaken. Any help understanding this would be very welcome!

Edit: I understand I can't call the lower() method inside the format call (though it'd be neat if that were possible); my question is why doing so throws an AttributeError. This error seems misleading in this case.

dreftymac
  • 31,404
  • 26
  • 119
  • 182
duhaime
  • 25,611
  • 17
  • 169
  • 224

2 Answers2

11

You can't call a method from within a format specification. Dot notation inside the format specifier is a way to look up attribute names and render their values, not to call functions.

0.lower() tries to look up an attribute on the string literally named "lower()" - the equivalent of getattr(some_string, 'lower()'). You need to call the method before formatting.

>>> '{0.lower()}'.format('A')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'lower()'
>>> '{0}'.format('A'.lower())
'a'
snakecharmerb
  • 47,570
  • 11
  • 100
  • 153
4

As others have said, you can't do this in a format expression. It would work in an f-string though:

a = "A"
print(f"{a.lower()}")
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • However unlike `str.format`, python `f-string` does not support deferred evaluation ... as seen in this post https://stackoverflow.com/questions/42497625/how-to-postpone-defer-the-evaluation-of-f-strings – dreftymac Jun 16 '21 at 02:48