Q:

Replacing multiple words in a string from different data sets in Python

Essentially I have a python script that loads in a number of files, each file contains a list and these are used to generate strings. For example: "Just been to see $film% in $location%, I'd highly recommend it!" I need to replace the $film% and $location% placeholders with a random element of the array of their respective imported lists.
I'm very new to Python but have picked up most of it quite easily but obviously in Python strings are immutable and so handling this sort of task is different compared to other languages I've used.
Here is the code as it stands, I've tried adding in a while loop but it would still only replace the first instance of a replaceable word and leave the rest.
#!/usr/bin/python
import random

def replaceWord(string):
   #Find Variable Type
   if "url" in string:
       varType = "url"
   elif "film" in string:
       varType = "film"
   elif "food" in string:
       varType = "food"
   elif "location" in string:
       varType = "location"
    elif "tvshow" in string:
        varType = "tvshow"

   #LoadVariableFile
   fileToOpen = "/prototype/default_" + varType + "s.txt"
   var_file = open(fileToOpen, "r")
   var_array = var_file.read().split('\n')

   #Get number of possible variables
   numberOfVariables = len(var_array)

   #ChooseRandomElement
   randomElement = random.randrange(0,numberOfVariables)

   #ReplaceWord
   oldValue = "$" + varType + "%"
   newString = string.replace(oldValue, var_array[randomElement], 1)

   return newString

testString = "Just been to see $film% in $location%, I'd highly recommend it!"
Test = replaceWord(testString)

This would give the following output: Just been to see Harry Potter in $location%, I'd highly recommend it!
I have tried using while loops, counting the number of words to replace in the string etc. however it still only changes the first word. It also needs to be able to replace multiple instances of the same "variable" type in the same string, so if there are two occurrences of $film% in a string it should replace both with a random element from the loaded file.

A:

The following program may be somewhat closer to what you are trying to accomplish. Please note that documentation has been included to help explain what is going on. The templates are a little different than yours but provide customization options.
#! /usr/bin/env python3
import random

PATH_TEMPLATE = './prototype/default_{}s.txt'

def main():
    """Demonstrate the StringReplacer class with a test sting."""
    replacer = StringReplacer(PATH_TEMPLATE)
    text = "Just been to see {film} in {location}, I'd highly recommend it!"
    result = replacer.process(text)
    print(result)

class StringReplacer:

    """StringReplacer(path_template) -> StringReplacer instance"""

    def __init__(self, path_template):
        """Initialize the instance attribute of the class."""
        self.path_template = path_template
        self.cache = {}

    def process(self, text):
        """Automatically discover text keys and replace them at random."""
        keys = self.load_keys(text)
        result = self.replace_keys(text, keys)
        return result

    def load_keys(self, text):
        """Discover what replacements can be made in a string."""
        keys = {}
        while True:
            try:
                text.format(**keys)
            except KeyError as error:
                key = error.args[0]
                self.load_to_cache(key)
                keys[key] = ''
            else:
                return keys

    def load_to_cache(self, key):
        """Warm up the cache as needed in preparation for replacements."""
        if key not in self.cache:
            with open(self.path_template.format(key)) as file:
                unique = set(filter(None, map(str.strip, file)))
            self.cache[key] = tuple(unique)

    def replace_keys(self, text, keys):
        """Build a dictionary of random replacements and run formatting."""
        for key in keys:
            keys[key] = random.choice(self.cache[key])
        new_string = text.format(**keys)
        return new_string

if __name__ == '__main__':
    main()

