0

I have a text file where most of the text is boilerplate, with around two dozen variables that I'm changing in Python depending on the room that the file pertains to. Which method of replacing the text is "better", wrapping the entire text file into one big triple quoted f'string', or stacking up a bunch of .replace() ?

The file isn't very big and there's only about 300 rooms, so in my case milliseconds don't really matter. I'm thinking that for readability and future edits the .replace() way would be better, but I don't want to create a bad habit if doing it that way is a bad idea. Thanks in advance for any help.

simplified pseudo code:

class Thing:
    def __init__(self, name, var1, var2, var3):
        self.name = name
        self.var1 = var1
        self.var2 = var2
        self.var3 = var3


def doing_it_the_replace_way(thing):
    with open('template.txt', 'r') as file:
        file_data = file.read()

    file_data = file_data.replace('placeholder_name', 'name')
    file_data = file_data.replace('placeholder1', 'var1')
    file_data = file_data.replace('placeholder2', 'var2')
    file_data = file_data.replace('placeholder3', 'var3')    # etc.
    with open('output file.txt', 'w') as file:
        file.write(file_data)

def doing_it_the_f_string_way(thing):
    file_data = f"""This is the entire template text from {thing.var1} about the time I got a
                {thing.var2} stuck in my {thing.var3} at band camp."""
    with open('output file.txt', 'w') as file:
        file.write(file_data)
logan
  • 55
  • 6
  • 1
    How about using [string.format()](https://www.w3schools.com/python/ref_string_format.asp)? – Alok Aug 17 '20 at 18:51
  • 1
    If you're reading the string from a file, you might find it's a bad idea to `eval` it like an f-string. Something like `str.format()` with keyword arguments might be a better idea. https://stackoverflow.com/questions/47339121/how-do-i-convert-a-string-into-an-f-string – Pranav Hosangadi Aug 17 '20 at 18:52
  • If I went the f route the contents of the file would be one long variable file_data and then the only file operation would be file.write(file_data). I'll add that part to the question – logan Aug 17 '20 at 20:10

1 Answers1

2

I'd use neither.

Using regex will be safer (ie you don't need to f-string and eval the entire file) and scalable (you don't need 30 calls to str.replace if you have 30 variables, just an entry in the mapping dict).

import re

table = {'<time>': '12:00',
         '<date>': '1.1.1970'}

# imagine this being read from a file
string = '<time>, fixed text, <date>'
print(re.sub(r'(<.+?>)', lambda s: table.get(s.group(1), s.group(1)), string))

outputs

12:00, fixed text, 1.1.1970

Adapting to your case (where the values are attributes of an object)

All you have to do is use the object as the values for mapping dict.

...
thing = Thing('name', 'a', 'b', 'c')

table = {'<time>': thing.var1,
         '<date>': thing.var2}
...

This can become cumbersome if you need to do something more complex (like if you have multiple objects) but of course it can be improved depending on your exact use-case.

For example, if the name of the placeholders coincide with the name of the attributes in the object you can just use vars as the mapping (don't forget to remove the < and > from the regex capturing group):

import re

class Thing:
    def __init__(self, name, var1, var2, var3):
        self.name = name
        self.var1 = var1
        self.var2 = var2
        self.var3 = var3


thing = Thing('name', 'a', 'b', 'c')
string = '<var1>, fixed text, <var2>'
print(re.sub(r'<(.+?)>', lambda s: vars(thing).get(s.group(1), s.group(1)), string))

outputs

a, fixed text, b
DeepSpace
  • 78,697
  • 11
  • 109
  • 154
  • Thank you. Your example makes perfect sense even to someone who's never messed with regex. I think it might not work for the bigger picture of what I'm doing since I'm creating a lot of the variable inside @property setters. That is unless I write the object's properties out to a dict and then use regex?? If nothing else it would be that much more of a learning experience. The readability would be nice doing it your way. – logan Aug 17 '20 at 20:22
  • @logan I updated the answer with some suggestions – DeepSpace Aug 17 '20 at 20:34