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)
3
  • 1
    How about using string.format()? Commented Aug 17, 2020 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. stackoverflow.com/questions/47339121/… Commented Aug 17, 2020 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 Commented Aug 17, 2020 at 20:10

1 Answer 1

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
Sign up to request clarification or add additional context in comments.

2 Comments

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 I updated the answer with some suggestions

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.