简体   繁体   中英

Is there a reason to be able to declare a variable inside .format?

I'm following a certain Python tutorial online and the tutor is teaching about the .format() method.

For example:

print("{}, {} and {} are colors.".format("Red", "Blue", "Green"))

will output

Red, Blue and Green are colors.

It's also possible to use indexing (maybe this is not the right wording):

print("{0}, {1} and {2} are colors.".format("Red", "Blue", "Green"))

that would output the same thing.

However, he then proposed an alternative of declaring variables (again, probably this is not the right wording) like the following:

print("{r}, {b} and {g} are colors.".format(r="Red", b="Blue", g="Green"))

That again outputs the same result.

Is there any advantage of using variables like r , b and g inside the .format() method?

One thing I thought about it is that I could use these variables later on in the program but if I try to use them I get a NameError: name 'r' is not defined .

Is there any advantage of using variables like r , b and g inside the .format() method?

Using keyword arguments is especially useful when you need to refer to the same object more than once.

Demo:

>>> class Signal: 
...:     status = 'on' 
...:     color = 'red' 
...:                                                                                                                   
>>> 'the signal is {sig.status} and the color is {sig.color}'.format(sig=Signal)                                       
the signal is on and the color is red

You could have achieved the same with

>>> 'the signal is {0.status} on the color is {0.color}'.format(Signal)                                         
the signal is on on the color is red

but using names makes the string easier to interpret for humans that read the code.

In addition, keyword arguments can be passed in any order, while you would have to make sure to pass positional arguments in the correct order. Here's another example which hopefully demonstrates the usability advantages of keyword-arguments.

>>> class Fighter: 
...:     def __init__(self, name, attack, defense): 
...:         self.name = name 
...:         self.attack = attack 
...:         self.defense = defense                                                                                                                          
>>>                                                                                                                                                          
>>> Bob = Fighter('Bob', 100, 80)                                                                                                                            
>>> Tom = Fighter('Tom', 80, 90)                                                                                                                             
>>> template = 'Attacker {attacker.name} attempts hit at {defender.name} with {attacker.attack} (ATK) against {defender.defense} (DEF)'                                  
>>>                                                                                                                                                          
>>> template.format(attacker=Bob, defender=Tom)                                                                                                              
'Attacker Bob attempts hit at Tom with 100 (ATK) against 90 (DEF)'
>>> template.format(defender=Tom, attacker=Bob)                                                                                                              
'Attacker Bob attempts hit at Tom with 100 (ATK) against 90 (DEF)'

0, 1, 2 etc. simply acts as the placeholders for printing. For ex:

print("{0}, {1} and {2} are colors.".format("Red", "Blue", "Green"))

prints

Red, Blue and Green are colors.

whereas

print("{1}, {0} and {2} are colors.".format("Red", "Blue", "Green"))

prints

Blue, Red and Green are colors.

On the other hand,

print("{}, {} and {} are colors.".format("Red", "Blue", "Green"))

would simply print in the order of arguments provided to format .

However, when you do,

print("{r}, {b} and {g} are colors.".format(r="Red", b="Blue", g="Green"))

you are simply kind of creating or redefining the place holders from 0 , 1 and 2 to a , b and c whose scope is local to the format / print command

Sometimes names are just easier to comprehend, and sometimes you want to pick out some of the elements of a dictionary with more options.

Say you have a configurable set of strings that provide information on your system, where you put information on a wide variety of subjects in a dictionary. Like a flight system:

information = {
    'speed': 10
    'altitude': 2500
    'time': datetime.datetime(2018, 12, 30, 18, 53, 44)
    'heading': 249,
    'eta': datetime.datetime(2018, 12, 30, 22, 30, 00)
    'flightnumber': 'MPA4242',
    'destination': 'LGW',
    'destination_name': 'London Gatwick Airpoirt',
    ...
}

you can use {name} fields (with or without formatting) in your configurable strings:

short_status = 'Current status: flying at {speed} mph at {altitude} feet, heading {heading} degrees, ETA {eta:%H:%M}'
captains_message = '''
    Hi, this is your Captain speaking. We are currently flying at {altitude} feet,
    at a speed of {speed} mph, making good time to arrive at {destination_name} in
    good time for our scheduled {eta:%H:%M}' landing.
'''

and you can re-use the same dictionary for any of those messages:

print(short_status.format(**information))
print(captains_message.format(**information))

Note how having used names, the string templates are a lot more informative then when you use auto-numbered or explicitly numbered fields, you can see, at a glance, immediately what kind of information is going to be slotted there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM