'Question about the magic 8 ball program with a list from Automate the Boring Stuff with Python
I am having trouble understanding the magic 8 ball program in the Automate the Boring Stuff with Python book. The program basically has a bunch of messages in a list and than uses the random.randint method to choose one of the messages randomly. The code is as follows:
import random
messages = ['It is certain',
'It is decidedly so',
'Yes definitely',
'Reply hazy try again',
'Ask again later',
'Concentrate and ask again',
'My reply is no',
'Outlook not so good',
'Very doubtful']
print(messages[random.randint(0, len(messages) - 1)])
As you can see this program is fairly simple. My question is about the last line. Why is he subtracting 1 from the length of messages? Shouldn't the random.randint method choose something from all the messages, not just some. There are 9 messages, but subtracting one means that only 8 messages are going through to the random.randint method. Can someone please explain why he is subtracting 1 from the length of messages?
Thanks in advance for your reply!
Solution 1:[1]
Python indexing starts at 0, not 1. If you have 9 entries in the list, you need a random integer in the range 0-8.
Solution 2:[2]
messages
is a list. Lists are indexed from 0 to n-1, where n is the number of elements in the list, which is also the length as returned by the length
function. However you don't really need to worry about that, as you can just use
print(random.choice(messages))
which will produce the same result as random.choice
will select a random element from a list.
Solution 3:[3]
Let's say you have a list with 3 objects and you want to print the 3rd element of the list.
>>> s = [1,2,3]
>>> print(s[3])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
This gives the index out of range error because the elements in a list are counted from zero, not one.
But if you check the length of the list, it will say that this list has 3 elements.
>>> s = [1,2,3]
>>> print(len(s))
3
When you pass the len value of the list in random.randint(0,len(s))
, the range becomes 4 (0-3) rather than 3 (0-2).
To tackle this, we substract the len by one random.randint(0,len(s)-1)
and make the range 3 (0-2).
Now randint cannot pick number 3 and pass it to list index, so no more errors.
Solution 4:[4]
"Shouldn't the random.randint method choose something from all the messages, not just some."
The random.randint method does not know anything about the list. If we look at the documentation for randint:
random.randint(a, b)
Return a random integer N such that a <= N <= b.
So if we do random.randint(1, 3) it will either give us 1, 2, or 3.
To get a random number from 0 to 9, we would do as you said, just doing random.randint from 0 to len(messages), and then use that number to get a random index from the list. The problem is that your list is 9 items, so the indexes are from 0 to 8 (the last item would be messages[8]). This is called 0 based indexing. The location of the last index is always equal to the length minus one. So that is why we are doing minus one. I just wanted to clarify and expand this, since some of what you were describing was not quite accurate.
Solution 5:[5]
print(messages[random.randint(0, len(messages) - 1)])
0 is the first index of the list and -1 is the last index of the list. This line of code prints a random index from the list between the first (0 - in this case "It is certain") and the last (-1 - in this case "Very doubtful). Im pretty amateur but i'm sure I read this in the book yesterday.
The book states "The benefit of this approach is that you can easily add and remove strings to the messages list without changing other lines of code."
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Prune |
Solution 2 | Deepstop |
Solution 3 | Vignesh SP |
Solution 4 | Community |
Solution 5 |