Reading a List with eval()
The other way: one prompt, and the user types the whole list. It is three lines shorter than the loop version and it hangs entirely on one new function — eval(), which takes a piece of text and runs it as Python.
1The program
Let the user type a whole list in one go, and report what came back.
# read the whole list in one go
numbers = eval(input('Enter a list: '))
print('The list is', numbers)
print('It has', len(numbers), 'items')
print('The first item is', numbers[0])Enter a list: [10, 20, 30] The list is [10, 20, 30] It has 3 items The first item is 10
One question instead of four. But the interesting part is what would have happened without the eval(), because that is the part the program hides:
# the same input, without eval()
numbers = input('Enter a list: ')
print('The value is', numbers)
print('Its length is', len(numbers))
print('Its first item is', numbers[0])
print('Its type is', type(numbers))Enter a list: [10, 20, 30] The value is [10, 20, 30] Its length is 12 Its first item is [ Its type is <class 'str'>
input() always hands back text — it has no idea you meant a list — and eval() is what turns those twelve characters into three numbers.2What eval() actually does
eval() takes a string, reads it as though you had typed it into a Python program, works it out, and hands back the answer. It is not about lists at all:
# eval() runs whatever the text says
print(eval('2 + 3'))
print(eval('10 * 4'))
print(type(eval('[1, 2, 3]')))
print(type(eval('10, 20, 30')))5 40 <class 'list'> <class 'tuple'>
eval('2 + 3')The text '2 + 3' is five characters. eval() reads them as Python, does the addition and hands back the number 5 — not the string '5'.
eval('[1, 2, 3]')Read as Python, square brackets with commas in them mean a list, so that is what comes back. Nothing here is special-cased for lists; it is just what that text means.
eval('10, 20, 30')And commas with no brackets mean a TUPLE. Same input as far as the user is concerned, different type — which is the first of the three traps below.
3The two ways, side by side
Step both programs forward together. Watch the left one grow an item at a time, and watch the right one pass through a piece of text on its way to becoming a list.
Four questions on the left, one on the right. Watch where the list comes from.
Nothing has run yet.
Nothing has run yet.
| with a loop | with eval() | |
|---|---|---|
| questions asked | n + 1 | 1 |
| lines of code | 6 | 3 |
| the user must know | nothing | how to type a list |
| a typo costs | one value | the whole run |
| casting | int() on each value | eval() does it |
| mixed types | awkward | free — [1, 'a', 2.5] |
4Three ways eval() bites
1. Forget the brackets and you do not get a list. The program runs, everything looks right, and the type is wrong:
Enter a list: 10, 20, 30 The list is (10, 20, 30) It has 3 items The first item is 10
Round brackets in the output, not square: that is a tuple, and the very next thing the program tries to do — append(), or numbers[0] = 5 — will fail, because a tuple cannot be changed.
2. A typo stops the program. Miss a bracket and the text is not legal Python, so eval() refuses it:
(the same program, with a bracket missing)Enter a list: [10, 20, 30
Traceback (most recent call last):
File "read_eval.py", line 1, in <module>
numbers = eval(input('Enter a list: '))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<string>", line 1
[10, 20, 30
^
SyntaxError: '[' was never closedType a bare word and you get a different refusal, because Python reads it as the name of a variable that does not exist:
(the same program, with a name typed instead of a list)Enter a list: Asha
Traceback (most recent call last):
File "read_eval.py", line 1, in <module>
numbers = eval(input('Enter a list: '))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<string>", line 1, in <module>
NameError: name 'Asha' is not definedSyntaxError — the text is not Python at all. A bare word is a NameError — the text is Python, and it means “the variable called Asha”, which does not exist. Typing 'Asha' with quotes would have worked, which tells you how much the user is expected to know.3. It runs whatever it is given. This is the serious one. eval() does not check that the text is a list — it runs it, whatever it is. Anything the user could type into a Python program, they can type into that prompt, and it will be carried out. For a classroom exercise that is fine. For a program handling other people's data it is a real problem, which is why professional code avoids eval() on anything a stranger typed.
5Which one should you use?
It is what papers ask for by name, it works for a user who knows nothing about Python, and every value is cast where you can see it.
Testing something quickly, or a program whose user is you. One line, mixed types for free, and no ceremony.
input().split() chops one typed line into a list of strings at the spaces, so 10 20 30 becomes ['10', '20', '30']. It needs no brackets and no eval() — but the items are text, so a second loop has to cast them before they can be added up.# a third way: split one line at the spaces
text = input('Enter the numbers, separated by spaces: ')
pieces = text.split()
numbers = []
for p in pieces:
numbers.append(int(p))
print('As text: ', pieces)
print('As numbers:', numbers)Enter the numbers, separated by spaces: 10 20 30 As text: ['10', '20', '30'] As numbers: [10, 20, 30]
6Recap
Typing [10, 20, 30] gives a 12-character string whose first item is '['. Nothing about the brackets makes it a list.
eval('2 + 3') is 5. It is not a list function — a list is just what that particular text happens to mean.
eval('10, 20, 30') gives (10, 20, 30), which cannot be appended to or changed. The program runs and the type is wrong.
SyntaxError for a missing bracket, NameError for a bare word. The loop version loses one value; this one loses everything.
- 1
Read a list with
eval()and print its largest item, withoutmax().Hint · One line to read it, then the champion loop from two pages back.
- 2
Read a list with
eval()and printtype(numbers)before anything else.Hint · Try it with brackets and without, and watch the type change from list to tuple.
- 3
Read two lists with
eval()and print the items they have in common.Hint · A loop inside a loop, or
inon the second list. - 4
Read a line of numbers with
split()and add them up.Hint · Remember the pieces are text:
total = total + int(p). - 5
Write the same program twice — once with the loop, once with
eval()— and count the lines of each.Hint · Then decide which you would hand to somebody who does not know Python.
numbers = input('Enter a list: ') and the user types [10, 20, 30]. What is len(numbers)?
A user types 10, 20, 30 with no brackets into an eval() prompt. What comes back?
Which is the better choice for a program a stranger will use?