Skip to content
VLSI Mentor

Python Part I · Module 5 · Lists

Building Lists from Other Values

Every list so far has been written out by hand or produced by an operation on another list. Often the values you want are already somewhere else — in a piece of text, in a run of numbers, in something a tool handed back. The list() function builds a list out of any of those, and it is genuinely useful. It is also one of the most over-used calls in beginner Python, wrapped around things that are already lists by people who have not checked. This chapter covers what the conversion does, the one case where it is the only way to see what you have got, and how to tell a conversion you need from one you wrote out of habit. It also closes Module 5.

Foundation12 min readPythonPart IFundamentalsListsConversion

Part I · Module 5 · Chapter 5.9 · Building Lists from Other Values

1. list(): Build a List From Something Else

list() is a built-in function, in the same family as len(), str() and int() from Module 2. Give it something that supplies values in order and it builds a list of them:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print(list("abc"))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['a', 'b', 'c']

A string supplied its characters one at a time, and list() collected them into a list of three one-character strings.

That is the same behaviour you have already seen twice. Chapter 4.9 showed "-".join("PASS") producing P-A-S-S, and Chapter 5.6 showed extend("bc") adding two characters. All three are the same fact: a string supplies its characters in order, and anything that takes values in order will take them from a string.

Called with nothing, it builds an empty list:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print(list(), [])
print(list() == [])
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
[] []
True

list() and [] produce the same value. Write [] — it is shorter and more direct. list() earns its place when it is converting something.

2. The One Case You Actually Need It For

Here is where converting a string to a list is genuinely the right move, and it closes a loop with Chapter 4.11.

A string cannot be changed. If you need to work on text position by position — swapping characters around, replacing one in the middle — you cannot do it to the string. You can convert it to a list, change the list, and build a string back:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
chars = list("PASS")
print(chars)
print("".join(chars))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['P', 'A', 'S', 'S']
PASS

list() on the way out, "".join() from Chapter 4.9 on the way back. The list in the middle is mutable, so everything in Chapter 5.3 applies to it.

And len() behaves exactly as you would expect across the conversion:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print(len(list("reset_n")))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
7

Seven characters became seven elements.

3. Converting a List Gives You a Copy

list() applied to a list does not do nothing — it builds a new list with the same elements:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
a = ["x", "y"]
b = list(a)
b.append("z")
print(a, b)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['x', 'y'] ['x', 'y', 'z']

a is unchanged, so b is an independent list. That is the third copying form from Chapter 5.8, alongside a.copy() and a[:], and all three behave identically.

Which one to write is a readability question. a.copy() says "copy"; list(a) says "make a list of this", and is the natural choice when you are not sure what you were given and want a list either way.

4. Converting a Range

range produces a run of whole numbers, and it is the other thing the canonical curriculum names for this chapter:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print(list(range(4)))
print(list(range(1, 5)))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
[0, 1, 2, 3]
[1, 2, 3, 4]

You need exactly two facts about range to read those lines. It produces the numbers from the start up to but not including the stop — the same boundary rule as slicing in Chapter 4.5 — and with one argument the start is 0. So range(4) is 0, 1, 2, 3, and range(1, 5) is 1, 2, 3, 4.

Module 10.4 teaches range properly, because its real job is counting in loops rather than being converted. Here it is only something being converted.

But there is one thing worth seeing now, because it explains why this conversion exists at all:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print(range(4))
print(type(range(4)))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
range(0, 4)
<class 'range'>

Printing a range does not show you its numbers. It shows you the range itself, which is a range value, not a list. range describes a run of numbers without ever building a list of them — which is efficient, and unhelpful when you want to look at them.

5. What list() Refuses

list() needs something that supplies values in order. A single number does not:

Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
print(list(4210))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: 'int' object is not iterable
Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
print(list(None))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: 'NoneType' object is not iterable

Iterable is the word in that message and it is worth adopting, because it names something you have been observing all module: a value that can supply its contents one at a time. A string is iterable — it supplies characters. A list is iterable — it supplies elements. A range is iterable — it supplies numbers. A number is not; it is one quantity, with no contents to hand out.

That is also the honest answer to why len(4210) failed back in Chapter 4.6, and why "-".join(42) would fail. Same underlying reason, three different messages.

If you want a single value in a list, put it in one directly — [4210] — rather than converting.

6. The Conversions You Do Not Need

This is what the canonical purpose asks for, and it is the part most tutorials skip.

split() already returns a list. Chapter 4.8 established that, and wrapping it again does nothing:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
line = "smoke reset burst"
print(line.split())
print(type(line.split()))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['smoke', 'reset', 'burst']
<class 'list'>
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
line = "smoke reset burst"
print(list(line.split()) == line.split())
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
True

list(line.split()) builds a second list with identical contents and throws the first away. It is not wrong, it is just noise — and noise in code costs a reader time.

A list you were given is already a list. Calling list() on it is only meaningful if you specifically want a copy, as Section 3 described. If you do not, drop it.

There is a real cost to the habit beyond noise. list(something) builds a whole new list, and on a large one that is real work done for nothing. More importantly, a reader who sees list(...) reasonably assumes a conversion was needed, and spends time working out why.

7. Predict, Run, Observe

Predict every line before reading on.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print(list("PASS"))
print(len(list("PASS")))
print(list(range(3)))
print(range(3))
print(list([1, 2]))
print(list() == [])
print("".join(list("abc")))

The verified output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['P', 'A', 'S', 'S']
4
[0, 1, 2]
range(0, 3)
[1, 2]
True
abc

The fourth line is the one to check yourself on. print(range(3)) shows range(0, 3) — not [0, 1, 2]. If you predicted the numbers, you assumed a range is a list; it is not, and Section 4 is why the conversion exists.

The last line is the round trip from Section 2: characters out, characters back, original string returned.

8. Exercises

Exercise 1 — convert and count. Write the line producing a list of the characters of "reset_n", and the line producing its length. Then produce the original string back from the list.

Exercise 2 — predict. Give each result without running it, then verify: (a) list("ab") (b) len(list("ab")) (c) list(range(2)) (d) list(range(2, 5)) (e) list([]) (f) list()

Exercise 3 — needed or habit. For each, say whether the list() call does something useful, and rewrite the ones that do not: (a) fields = list("a,b".split(",")) (b) chars = list("PASS") (c) nums = list(range(5)) followed by printing nums (d) backup = list(tests) where tests must stay unchanged (e) names = list(["smoke", "reset"])

Exercise 4 — the range surprise. Explain in two sentences why print(range(3)) does not show three numbers, and give the line that does.

Exercise 5 — read the error. Run list(4210) and write down the exact message. Explain what "iterable" means in one sentence, and give two other values that would produce the same kind of error.

Exercise 6 — the round trip. Starting from "FAIL", produce the list of its characters, change the first element to "P", and build the resulting string. Say which chapter's rule made the middle step possible and which made it impossible on the string itself.

Exercise 7 — copy or convert. Given a list results that must not be changed, write two different lines that give you an independent list to work on. Say which you would submit for review and why.

9. Summary

  • list(x) builds a list from anything that supplies values in order.
  • list("abc") gives ['a', 'b', 'c'] — a string supplies its characters, the same fact behind join and extend.
  • list() with nothing is []. Write [].
  • Converting a string to a list, changing it, and joining back is the standard way to edit text position by position, and it works because a list is mutable and a string is not.
  • list(a) on a list is a copy — the third form alongside a.copy() and a[:].
  • range is not a list. print(range(4)) shows range(0, 4); list(range(4)) shows [0, 1, 2, 3]. Module 10.4 teaches range properly.
  • list() refuses a value with no contents — TypeError: 'int' object is not iterable.
  • Iterable names something you already knew: a value that supplies its contents one at a time.
  • split() already returns a list. Wrapping it is noise.
  • Ask what you have and what you need before converting. A list() call tells a reader a conversion was necessary.

That completes Module 5 — Lists.

You began the module able to work with one value at a time. You can now hold many values in one ordered collection; reach any element or run of them with the position rules strings already taught; change a list in place by replacing, adding, inserting and removing; order results and know which tool preserves the original; combine and repeat lists and predict which operation builds something new; store a table as a list of rows and reach any cell; and — the one that matters most — explain exactly why changing a list through one name is visible through another, and copy deliberately when you need independence.

That last point is worth dwelling on. Chapter 5.8 is the first genuinely subtle thing in this course, and it is subtle only because Module 2's model of names and values is being taken seriously. Nothing new was invented to explain it.

Two things are still missing and you will have felt both. You cannot yet decide — do one thing when a test failed and another when it passed. And you cannot yet repeat — do the same work to every element without naming each one. Those are Modules 9 and 10, and lists are what they will mostly be working on.

Before that, Module 6 — Tuples takes the collection you now know well and removes one property from it: a tuple is ordered like a list and cannot be changed, like a string. After this module you are in a good position to ask the right question about that — not "what can it do?" but "what is it for, given that it can't change?"

Where this fits

Part of the Python curriculum.