0

Edit: made some changes - now the program finishes, but still doesn't output anything.

import random

dict = open("british-english")
word_list = dict.readlines()

def generate():
    global word_list
    prompt = random.choice(word_list)
    if len(prompt) < 3:
        generate()
    else:
        return prompt

generate()



print(prompt)

I have written the below code to try and generate a random word of three letters or more from the brisih-english text file I found on my linux machine. I have copied the file to the same directory as my .py file. When I run the program in the terminal, I get no output, but the program seems to run infinitely. I am still a beginner at this, but this seems like such a simple program that I wonder what I could be missing. I already ran some tests to print different elements of the list to make sure I could access the words, which worked fine.

import random

#list contains 101,825 elements
dict = open("british-english")
word_list = dict.readlines()

prompt = ""

def generate():
    global dict
    i = random.randint(0, 101824)
    prompt = word_list[i]
    return prompt

while len(prompt) < 3:
    generate()

print(prompt)
Donagh
  • 89
  • 2
  • 10
  • Hint: what does the line `global dict` do inside `generate`? Taking that into consideration, when the condition `len(prompt) < 3` is checked, what do you expect the value of `prompt` to be, and why? What is that value's `len`? – Karl Knechtel May 15 '20 at 16:29
  • I thought global was necessary for a function to access a variable defined in the main body. I expect len(prompt) to return the number of letters i.i. the length of the string. Am I wrong? – Donagh May 15 '20 at 16:31
  • BTW: to select one of the `word_list` elements randomly, just use `random.choice`. That way, you don't have to worry about how long the list is, and the code won't break if the file changes. Also, instead of repeating until you find a long enough word, you could just remove the short words from the list first. – Karl Knechtel May 15 '20 at 16:31
  • Just realised I don't need dict inside the function any more - in an earlier version I think I had the readlines bit inside the function. – Donagh May 15 '20 at 16:32
  • Now, notice how your current code does **not** say `global prompt`? Therefore, does `generate` access the global variable `prompt`? Now, what about the while loop? Is it inside a function? Therefore, is it using the global variable? – Karl Knechtel May 15 '20 at 16:32
  • "I expect len(prompt) to return the number of letters i.i. the length of the string." Okay - and *what is the string* at that point? Why? How many letters does that string have? Is that value less than three? – Karl Knechtel May 15 '20 at 16:33
  • OK - I have changed it to this, and now the program doesn't hang, but I also get no output. ' dict = open("british-english") word_list = dict.readlines() def generate(): global word_list prompt = random.choice(word_list) if len(prompt) < 3: generate() else: return prompt generate() print(prompt) ' – Donagh May 15 '20 at 16:36
  • OK - can't figure out how to include new lines in a comment. I'll update my question with my new code. – Donagh May 15 '20 at 16:39
  • Comments don't support formatting like that, no. But you're still missing the point. Why do you expect `prompt` to stop being equal to `""` outside the function, and instead become equal to what you set it to inside the function? – Karl Knechtel May 15 '20 at 16:40
  • @KarlKnechtel is that not what 'return' does? If not, am I better off not defining prompt before the function? Earlier I got an error saying 'prompt not defined', which is why I added that line, but it might work now given the other changes I've made. I'll try it. – Donagh May 15 '20 at 16:44
  • "Is that not what 'return' does?" No, and you really need to study that, too. Think about it: if I do `return 0`, should the value of zero change? Functions return *values*, not variables. – Karl Knechtel May 15 '20 at 17:01

2 Answers2

1
prompt = ""

This is a global variable.

def generate():
    global dict
    i = random.randint(0, 101824)
    prompt = word_list[i]
    return prompt

Because this code does not say global prompt, the global variable prompt is therefore not modified by prompt = word_list[i].

while len(prompt) < 3:
    generate()

Each time through the loop, the value returned by generate is ignored, because nothing is done with the value. len(prompt) continues to use the "" value from above, which is shorter than 3 characters; thus the loop cannot break.

You should not use a global variable for this. You should instead write code that actually uses the return value. For example:

prompt = generate()
while len(prompt) < 3:
    prompt = generate()

These lines would continue to work if put inside another function, because they take the value returned from generate() and give it a name that can be used locally.


Notice that generate does make use of the global variable word_list, despite that there also is no global word_list. You do get read-only access to global variables automatically. But if you have a local variable with the same name, it is used preferentially.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • I feel like I finally understand global variables now. Thank you so much - my code is now working as I want it to! – Donagh May 15 '20 at 16:47
0

It's due to your while loop initialized to empty so the size is 0. Your generate function that you declared there is merely defining the function, and it doesn't get execute unless you call it. So you could call it once right before the while loop if you're intend to get generate to call before starting the loop.

noobius
  • 1,529
  • 7
  • 14
  • Thanks for the answer. I'm not sure I full understand, but I have added a new line to call the function just before the while loop, and I still get the same result. My thinking was that I set prompt = "" at the beginning, so len would be > 3, causing the while loop to start and call the function - am I wrong? – Donagh May 15 '20 at 16:27