mecook112
mecook112

Reputation: 3

How to convert Python2 string with formatting into the new f string used in python3

I am working on converting some Python 2.7 code to reflect a more Python 3.10 method and came across this scenario. A string variable is holding the formatting and then later on variables are added to that string. Not sure how to go about getting rid of the % method and using a f string instead or if that is even necessary.

Here are the two variables.

temp1 = '%-5s %-12s%3s %-10s %-20s %-8s%-18s%-4s %-4s %-46s %-16s\n'
header = temp1 % ('ID','SerialNumber','Cabinet','Type','Last Update','Status','Result','Fail','Pass','Instructions','Resolution')

Output for header is:

ID SerialNumberCabinet Type Last Update Status Result Fail Pass Instructions Resolution

I am wanting to get rid of the % in header and use an f string instead or write this better in Python 3.x if possible.

Upvotes: 0

Views: 71

Answers (1)

user23307932
user23307932

Reputation: 178

Disclaimer

I have introducd another variable data to store your tuple, this is not necessary, but I hope it gives the examples a better readability.


There are three ways of the new-style format strings that you can use. Which one is the best depends on the situation you are using it.

And there is also a lot of discusion which one is "the best" in my opinion the best is the one that fits your custom needs, which also includes readability in your coding team, if you have one.

Here are the alternatives:

F-String

Downside: You can not split into formatting and data, like your example does. Normal use case is not yours, the normal use case is, if you have a bunch of local / nonlocal variables and want to join them in a cool logging message or a custom __str__ or __repr__

data = ('ID','SerialNumber','Cabinet','Type','Last Update','Status','Result','Fail','Pass','Instructions','Resolution')
header = f'{data[0]:-5s} {data[1]:-12s}{data[2]:3s} {data[3]:-10s} {data[4]:-20s} {data[5]:-8s}{data[6]:-18s}{data[7]:-4s} {data[8]:-4s} {data[9]:-46s} {data[10]:-16s}\n'

.format with postional arguments

This is probaly what you want. Downside: you have to comment / document which data has to come in which order.

This one I have never used, because I prefer boilerplate over implicity, but that is just my opinion, I am sure there are use cases where this makes sense to use.

data = ('ID','SerialNumber','Cabinet','Type','Last Update','Status','Result','Fail','Pass','Instructions','Resolution')
temp1 = "{:-5s} {:-12s}{:3s} {:-10s} {:-20s} {:-8s}{:-18s}{:-4s} {:-4s} {:-46s} {:-16s}\n"
header = temp1.format(*data)

.format with keyword arguments

This is the same as above, just with another downside: You have to type much more code. And with the upside that your documentation is in the string. Also you do not need change your calls to .format, if you change the structure of your template string. Of course you have to change headerX in the string and in the kwargs of .format into something that makes sense. But I can't figure out what you are trying to do, so I kept it generic.

I like this one for serializing dataclasses. For example: "...".format(**vars(datacls_instance))

data = ('ID','SerialNumber','Cabinet','Type','Last Update','Status','Result','Fail','Pass','Instructions','Resolution')
temp1 = "{header1:-5s} {header2:-12s}{header3:3s} {header4:-10s} {header5:-20s} {header6:-8s}{header7:-18s}{header8:-4s} {header9:-4s} {header10:-46s} {header11:-16s}\n"
header = temp1.format(header1=data[0], header2=data[1], header3=data[2], header4=data[3], header5=data[4], header6=data[5], header7=data[6], header8=data[7], header9=data[8],header10=data[9], header11=data[10])

Upvotes: 0

Related Questions