1 Counting
Read the tutorial. Build it yourself is the other way to read this part.
just setuptally must count the words of a text. First we write a function that counts, and try it alone. Then the command reads a text, and prints what the function counts.
The code before this part. The code after it.
1.1 A function that counts
A word counter needs a way to count. A function, count, takes a text and gives a dictionary from each word to how
many times it appears. It goes in src/tally/__init__.py, above main. The command does not use it yet.
A patch to src/tally/__init__.py.
In src/tally/__init__.py, count now stands above main. It splits the text at every space, tab and end of line. For each word, it
adds 1 to the count so far, and counts.get(word, 0) gives 0 for a word it has not seen.
uv run python -c "from tally import count; print(count('a b a'))"It prints {'a': 2, 'b': 1}, two of a and one of b. So the function works, though the command still has
nothing to count.
What changed
src/tally/__init__.py: a dictionary from each word to how many times it appears. 7 lines added. The file.- look at
counts[word] = counts.get(word, 0) + 1
- look at
The diff of src/tally/__init__.py
@@ -1,5 +1,12 @@
"""tally: count the words in a text."""
+def count(text):
+ counts = {}
+ for word in text.split():
+ counts[word] = counts.get(word, 0) + 1
+ return counts
+
+
def main() -> None:
print("tally: nothing to count yet")1.2 The command counts
count works, but the command still prints that it has nothing to count. main must read a text and print the
counts. It reads the file that the command names, or the standard input when the command names no file. The module
sys gives both the arguments of the command and the standard input.
A patch to src/tally/__init__.py.
In src/tally/__init__.py, import sys now stands under the docstring of the module. The first line of main
reads the text, from the file named in sys.argv[1] or from the standard input. The loop prints each word with
its count. sorted puts the words in alphabetical order.
echo "a b a" | uv run tallyIt prints 2 a and then 1 b. The command now counts.
What changed
src/tally/__init__.py:mainreads the text and prints the counts. 5 lines added, 1 removed. The file.- look at
for word, n in sorted(count(text).items()):
- look at
The diff of src/tally/__init__.py
@@ -1,5 +1,7 @@
"""tally: count the words in a text."""
+import sys
+
def count(text):
counts = {}
@@ -9,4 +11,6 @@ def count(text):
def main() -> None:
- print("tally: nothing to count yet")
+ text = open(sys.argv[1]).read() if len(sys.argv) > 1 else sys.stdin.read()
+ for word, n in sorted(count(text).items()):
+ print(n, word)