4

I was learning Python as a beginner. Recently I learnt about formatting methods, dictionaries and etc. Currently I was studying for loop and discovered a functioned called enumerate (probably nothing to do with is problem). I was applying what I had learnt till now by mixing everything. Suddenly I discovered that two format method acts differently!! How and why is this happening? Please explain.

Method 1:

nameAgeDictionary = {'Jack': 38, 'John': 51, 'Alex': 13, 'Alvin': 'Not Available'}

for index, name in enumerate(nameAgeDictionary):
    print('(%d) Name = %s, Age = %s' % (index+1, name, nameAgeDictionary[name]))  # Format_Method_1

Output:

(1) Name = Jack, Age = 38

(2) Name = John, Age = 51

(3) Name = Alex, Age = 13

(4) Name = Alvin, Age = Not Available

Method 2:

nameAgeDictionary = {'Jack': 38, 'John': 51, 'Alex': 13, 'Alvin': 'Not Available'}

for index, name in enumerate(nameAgeDictionary):
    print('({0:d}) Name = {1:s}, Age = {2:s}'.format(index+1, name, nameAgeDictionary[name])) # Format_Method_2

Output:

Traceback (most recent call last): File "PATH_to_File.py", line 3, in

print('({0:d}) Name = {1:s}, Age = {2:s}'.format(

ValueError: Unknown format code 's' for object of type 'int'

I have tried putting d in the place of s, on that case, it prints first 3 lines and gets stucked in last line (e.g. Not Available).

2
  • 1
    2.4.3. Formatted string literals. You can force the conversion to str with !. print('({0:d}) Name = {1:s}, Age = {2!s}'.format(index+1, name, nameAgeDictionary[name])) Commented May 12, 2021 at 20:21
  • Thank you! That is working! But as assumed in the answer by user_na, that in contrast to .format() the % formatting calls str as a fallback. What's your opinion on that? I am asking this to you as well as user_na wasn't completely sure of the reason. Commented May 12, 2021 at 20:31

1 Answer 1

4

As the type of the age is mixed (strand int), just don't specify the type.

for index, name in enumerate(nameAgeDictionary):
    print('({0:d}) Name = {1:s}, Age = {2}'.format(index+1, name, nameAgeDictionary[name])) # Format_Method_2

By doing this __str__ of the input should be called which savely converts the int to str. The result is:

(1) Name = Jack, Age = 38
(2) Name = John, Age = 51
(3) Name = Alex, Age = 13
(4) Name = Alvin, Age = Not Available

I assume (but I am not completly sure) that in contrast to .format() the % formating calles __str__ as fallback.

Update

Here is the proof that % formating is calling __str__:

class test():
     def __str__(self):
         return 'bar'
 
foo = test()
print('%s'%(foo))

prints

bar
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you! This is working totally fine! But I still don't understand this thing: Why is in method 1 it is still working even after specifying the type as a string? (e.g. with %s)? Why is method 1 not showing the error that Method 2 was giving me?
As I said, I assume that the first one calls __str__ in case the input is not a string as specified in the input, while the second one does not handle the error.
Oh! Accha, now I am starting to understand what might cause this behavior difference to happen. Thank you so much @user_na for elaborating this repeatedly :-)
Wow, great! Thank you so much for your help @user_na, without your help it would have remained as a confusion to me forever.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.