Collections of Values
Most computing involves creating collections of values and then manipulating those collections.
Why Programs Gather Values
Imagine a small program that asks a user for a sentence, counts its words, and then shows the result. Look closely at what the program handles. The user's input is not a single value. It is a group of characters. Each word is also a group of characters. The final count is built up from a group of earlier results. Almost nothing in this program is a single isolated value.
This is not a quirk of that one program. The source makes the point directly: most computing involves creating collections of values and then manipulating those collections. Much of programming is about gathering values together and then doing something with the gathered set. The rest of this article looks at the tool that makes that gathering possible, and at why the choice of that tool matters.
Containers as Classes
A container is a class whose main purpose is holding objects.
The definition has two parts worth keeping separate. The first part is that a container is a class. That makes it a design unit that a programmer writes or chooses. The second part is its main purpose, which is holding objects. A class that happens to store some data while mostly doing other work is not what this term names. The word container points to the job the class is built to do.
A useful way to picture a container is as a single object that stands for a group. Outside the container, the program refers to one thing. Inside it, several objects are held together. The relationship is one of containment: the container holds the objects, and the objects belong to it for as long as the program keeps them there.
The diagram shows only the containment relationship. It does not say how the objects are arranged in memory, and it does not say which operations the container offers. Those details depend on the particular class a programmer writes, and the source does not describe them.
Tracing a String Built Character by Character
The source gives a simple example of a collection in use: reading characters into a string and then printing the string. A string is a collection of characters. Building one character at a time is therefore a small instance of the broader pattern of gathering values and manipulating the result. Follow the state of the collection as each character arrives.
Hey- letters starts as an empty string, a collection with no characters yet
- the loop takes one character at a time from the text Hey
- each pass adds the current character to the end of letters
- print shows the whole collection only after every character has been added
Trace the state step by step. Before the loop runs, letters is an empty collection. After the first character, H, is added, the collection holds one character. After e is added, it holds two. After y is added, it holds all three, in the order they arrived. Only then does print use the whole collection and display Hey. This matches the three-part rhythm the source describes: the program first sets up the collection, then fills it one value at a time, and only then uses the whole collection.
What do you think happens?
If the loop had printed letters after each character instead of once at the end, what would the output be?
Reveal answer
H, then He, then Hey
Each pass adds one character, so the collection grows by one character per pass. Printing inside the loop would show the collection at each of its three intermediate states.
Creating, Filling, and Using a Collection
The source identifies a three-part rhythm that appears in almost every program that works with groups of values: create the collection, add values to it, and use the whole collection. The pipeline below shows the order. Notice that the middle stage can repeat many times before the program moves on.
Choosing a Container and Its Operations
The source identifies two steps as important in constructing any program. The first is providing suitable containers for a given task. The second is supporting those containers with useful fundamental operations. These two steps are linked. A container that holds the right kind of objects for a task makes the rest of the code easier to write. Operations that the container supports make the collected values usable without rewriting the same logic everywhere.
In practice, this means that the choice of container is a design decision, not an afterthought. When you start a program that gathers values, ask two questions. What kind of objects will the container hold for this task? Which fundamental operations will the rest of the program need to perform on it again and again? The answers shape the code that follows.
Common Mistakes With Collections
Common mistake Treating a collection as if it were a single value
What it looks likeThinking of the user's sentence as one item, when it is a group of characters that the program can process one by one.
Why it failsMost computing involves gathering values and then manipulating the gathered set. Ignoring the group leads to code that does not match what the program is actually working with.
Do this insteadAsk what the values are made of before writing code, and identify which parts are groups.
Common mistake Calling any class that stores some data a container
What it looks likeDescribing a class that mostly does calculations and keeps a single number as a container.
Why it failsThe source defines a container as a class whose main purpose is holding objects. Storing some data while doing other work does not match that purpose.
Do this insteadCheck whether the class's main job is holding a group of objects.
Common mistake Choosing a container without thinking about the operations needed
What it looks likePicking a container first and then writing awkward code to add, find, or change its values.
Why it failsThe source treats suitable containers and their useful fundamental operations as linked steps. A poor fit makes the rest of the code harder to write.
Do this insteadDecide which operations the task needs, then choose the container that supports them well.
Common mistake Assuming the diagram of a container shows how its contents are stored
What it looks likeExpecting a containment diagram to reveal the memory layout of the objects.
Why it failsA containment diagram shows only that the container holds the objects. Arrangement and operations depend on the specific class.
Do this insteadRead the containment picture as a statement about the relationship only, and look up the class's details separately.
Practice: Trace the Collection
Trace this program. Write down the value of letters after each pass of the loop, then state what print displays. letters = "" then for ch in "Cat": letters = letters + ch, then print(letters).
Hints
- Start with the empty string before the loop runs.
- Each pass adds exactly one character, in the order the characters appear in Cat.
- print runs only after the loop has finished.
Describe a small program of your own that gathers values into a collection and then uses the whole collection. Name the three stages: what you create, what you add, and what you do with the result. Then explain in one sentence why a suitable container would make the program easier to write.
Hints
- Choose a task that involves several items, such as a list of names or a sentence of words.
- Make sure the adding stage is clearly separate from the using stage.
Key Takeaways
- Most computing involves creating collections of values and then manipulating those collections, so gathering values is a central task in programming.
- A container is a class whose main purpose is holding objects. It can be pictured as one object that stands for a group, holding several objects inside it.
- Providing suitable containers for a task and supporting them with useful fundamental operations are important steps in building any program, and the two are linked.
- Reading characters into a string and then printing it is a simple collection pattern: create the collection, add values one at a time, then use the whole collection.