0
import random
foundwords = []
wordsDict = {}

#opens file and creates array words with all words as a seperate string item
with open("text", "r") as file:
    words = file.read().replace('\n',' ').split(' ')

#puts the words after all occurances of word in the list foundwords and returns it (read the code, it makes more sense than how I explain it)
def findwords(word):
    for g in range(len(words) - 1):
        if words[g] == word:
            if not words[g + 1] == '':
                foundwords.append(words[g + 1].lower())
    return foundwords

#uses the previous function on all words in the sample text and adds the list foundwords as a value with the word as a key
for i in range(len(words) - 1):
    foundwords = findwords(words[i])
    wordsDict.setdefault(words[i], foundwords)
    del foundwords[:]   

#chooses a random word from the foundwords list and returns it
def nextword(word):
    wordList = wordsDict[word]
    new = wordList[random.choice(wordList)]
    return new

#this is the function that runs. it creates the final list with a random word and calls the function above with that random word.
def assemble():
    final = [random.choice(words).capitalize()]
    final.append(nextword(final[-1]).lower())
    print(final)

assemble()

I'm in need of help on this project again!

This is a markov chain project. Each paragraph has a seperate function and I've labelled each of them.

I'm currently getting a KeyError that looks like this:

Traceback (most recent call last):
  File "main.py", line 31, in <module>
    assemble()
  File "main.py", line 28, in assemble
    final.append(nextword(final[-1]).lower())
  File "main.py", line 22, in nextword
    wordList = wordsDict[word]
KeyError: 'He' #<-- or whatever random word was chosen

I've concluded that the foundwords list is empty. The thing is that they are filled in the foundwords function and the for loop, but the lists are empty in the dictionary when called in the nextword function. How can I fix this problem?

I'm a beginner programmer, so if my code is inefficient, that's why. Please feel free to correct me, feedback is appreciated!

badcoder
  • 11
  • 4
  • Python isn't pass-by-value. You put a list in the dict, and then you wipe *that list*. The dict is now holding a reference to an empty list. – user2357112 Jan 10 '18 at 22:38
  • @user2357112 oh, how can I fix that problem? I can't not delete the list, or else the list would just grow bigger each time, correct? – badcoder Jan 10 '18 at 22:40
  • Make a copy? You've got more problems than that, though. – user2357112 Jan 10 '18 at 22:42
  • Why are you even using a global `foundwords` variable, anyway? – user2357112 Jan 10 '18 at 22:42
  • 1
    `wordsDict.setdefault(words[i], foundwords)` doesn't store a copy. It stores *the actual list*. Which you empty on the next line. – Martijn Pieters Jan 10 '18 at 22:46
  • @user2357112 Because I used it in several functions, I don´t know where to put it. – badcoder Jan 10 '18 at 22:52
  • There is no reason to share that variable across functions. – user2357112 Jan 10 '18 at 22:55
  • @user2357112 ok, i'll fix that, thank you so much! – badcoder Jan 10 '18 at 23:03
  • @user2357112: Pedantically, Python **is** pass-by-value. Practically no language I can think of would silenly copy a data structure like a list when storing in a mapping structure. (C++ might do it, depending on your exact code, but in idiomatic code the vector object would likely be shared even in C++.) – Daniel Pryden Jan 11 '18 at 01:18
  • My favorite explanation of what's actually happening here: https://nedbatchelder.com/text/names.html – Daniel Pryden Jan 11 '18 at 01:20
  • @DanielPryden: It's pass-by-value if you go by the Java "pass by value but you have to keep in mind that the value you're passing is a reference, not the actual object" terminology, but calling that "pass by value" without any qualification or explanation is more confusing than helpful, and when you add the explanation, the "pass by value" part doesn't really add to the explanation. – user2357112 Jan 11 '18 at 01:35
  • @user2357112. Meh. I could be convinced that "call-by-value" and "not call-by-value" are equally misleading here, albeit for different reasons. If you want clarity, use a term with the correct semantics: "call-by-object-sharing". – Daniel Pryden Jan 11 '18 at 01:39

0 Answers0