The following post contains a summary of the book titled Tiny Python Projects by Ken Youens-Clark

Chapter 1

  • The use of shebang at the top of the file is meant to indicate the type of program that can be used to run the code in the file. Most of the Programming languages - the program is written in a text file and relevant executable is used to invoke the program. The use of #! is a hint to the type of executable to be used for running the script
  • #!/usr/bin/env python3 is a way of telling OS to use environment command to find out the location of python3 and then use the relevant executable on the script
  • $PATH$ is a way of telling OS to find the relevant places where executables are available
  • The basic ideas behind creating an executable are two fold. First is to make sure that the OS recognizes the program as an executable. Second is to make sure that the executable is in a place that is mentioned in the $PATH$ variable
  • parser.parse_args asks the parser to parse any arguments to the program

Chapter 2

  • Have learned the way to write test-cases for simple programs
  • Learned about positional and optional arguments that can be specified via argparse library
  • Every feature of a program must have tests. Writing and running test suites should be an integral part of writing programs
  • Template that creates a basic python program with some skeleton. One can further work on this skeleton to fill up flesh

Chapter 3

  • reversed on a list gives a generator
  • If you want to take in a list of items representing a specific parameter, it is helpful to use nargs attribute in the parser.add_argument function
  • I haven’t learn any thing specific to Python lists. It is more about ways to capture the command line arguments, that I seem to be learning in all the first three chapters

Chapter 4

  • PEP guide says the variables need to be named with lowercase names separated by underscores
  • print takes an additional argument end which you can use to print a value to the screen without a newline

Chapter 5

  • The author’s solution was extremely elegant as compared to my solution
  • Misinterpreted the input to the program as a list instead of string
  • Was unnecessarily trying to use type in File argument parser
  • If you define multiple positional arguments, then it is important to define it in the correct order. The order of optional arguments is not important. They can be defined before or after the positional arguments
  • One can treat a regular string value as if it were a generator of values similar to a file handle. One can use the return value of io.IOStream as a “mock” file handle so that the code can handle the input seamlessly across file input and string input
  • To write a file in text mode, one can use the mode rt
  • STDOUT is always available via sys.stdout file handle
  • Never knew that one could simulate print functionality via
import sys

Chapter 6

  • To specify standard input as the default value, one needs to specify the sys.stdin in a list
  • I have spent quite a number of hours working through this chapter. Even though the code was simple, there was a quite a bit of learning on the way argparse module handles file input
  • Never knew that argparse module automatically handles the files and creates file handlers
  • Use of nargs for specifying one or more/ zero or more inputs
  • argparse.FileType('rt') will validate the user has provided a readable text file and will make the value available in your code as an open file handle

Chapter 7

  • Dictionary comprehension can be used to quickly create dictionaries
  • Defining file input arguments using argparse.FileType saves you time and code

Chapter 8

  • use of choices in the argparse field will automatically create the relevant error messages
  • trans object that is a result of applying maketrans function gives a dict
  • I had never know that one could write more than one conditional in a list comprehension
text = [
vowel if c in 'aeiou' else vowel.upper() if c in 'AEIOU' else c
for c in args.text

In the above code the function applies to each element of the list comprehension is the result of applying if, elif and else logic. However one never needs to use elif

  • map takes a function and an iterable. The result is another iterable where each element is the result of applying the function to each element of the iterable
  • The author presents eight different solutions and personally I liked the regex and list comprehension approaches
  • In regex you specify what you want to achieve and the rest is done by the regex engine. This is an example of declarative programming
  • map is called higher order function(HOF) because it takes another function as an argument
  • The chapter also introduces the concept of closures

Chapter 9

  • Learned about receiving int arguments via argparse
  • There are certain aspects that argparse cannot check. In all such cases, one needs to manually write logic that uses parser.error function to display message indicating erroneous arguments

Chapter 10

  • Learned to use a float argument to command line so that argparser can pick up the relevant input
  • random.seed() can accept None as input

Chapter 11

  • Had completely forgotten the option to define a reversed list of numbers using step argument

Chapter 12

  • Learned about using mapreduce for a very simple example
  • Learned about various ways of solving the problem posed in the chapter

Chapter 13

  • Spent one hour to get this right. Most importantly I have got all the tests right and have never looked at the solution
  • Why did it take one hour ? I think I was struggling to get the verse endings right with trailing newline characters
  • Also i realized that i was making a typo with twelfth
  • Learned about end argument in the print statement
  • When one mentions a file input with type attribute, argparse will automatically open the file in read mode or write mode
  • sys.stdout file handle is always open for writing
  • shadowing a variable or function means reusing an existing variable or function

Chapter 14

  • Learned about the use of using groups in pattern in regex
  • Use regex to match various patterns or figure out the absence of patterns
  • use of re.match to find out patterns in the form of a dictionary
  • use of re.findall to figure out missing patterns in the word
  • re.match starts from the beginning of the text
  • will match the string anywhere in the text
  • ran pylint and learned a few aspects of code formating

Chapter 15

  • Was struggling to split the text that had whitespace in the beginning. Never realized that one can use regex to split the text
  • If capturing parenthesis are used as a part of regex pattern, then the text of all groups are returned as part of the resulting list
  • The biggest learning from this chapter is re.split() function

Chapter 16

  • random.shuffle does in place sorting
  • splitlines method for file handler objects

Chapter 17

  • Regular expressions are almost like functions where we describe what we want as functions
  • Regex patterns with * and + are greedy patterns in that they match as many characters as possible. Adding ? after them makes it non-greedy
  • re.findall will find all the matching patterns in a string
  • re.sub will substitute the relevant matching patterns in a string with a replacement string
  • One can halt a program with a sys.exit call

Chapter 18

  • use of ord function

Chapter 19

  • Was a straightforward exercise using pandas
  • came across tabulate package to print tabular contents

Chapter 20

  • Spent at least 90 minutes on this exercise and managed to worked through it
  • cleaning text and extracting words cannot be accomplished with just splitting on white space. One must use regex to split the word that takes care of punctuation

Chapter 21

  • Took me two hours to work through all the tasks mentioned in the project
  • This was also the first time that I ran pytest on an intermediate file that wasn’t the master test file
  • spent sometime in understanding the board structure and ways to codify it
  • wrote four functions in so that i could reuse them at many places
  • once the helper functions were written, it did not take me a long time to code the main function that put all the pieces together
  • this chapter made me realize the importance of writing test scripts. Whatever be your proficiency in python, it is foolhardy to assume that the code that you have written will run without any problems. There will be edge cases and one will have to use a testing library to run through the tests and make sure that the code passes all the tests
  • used XOR operator in the code for the first time
  • author’s format_board function was much more elegant than my approach
  • author’s input validation code was also more elegant as it uses regular expression instead of manually checking the length of input arguments and using sets to check for the existence of a pattern
  • taught me a lot of stuff relating to various aspects of python as well as touch typing
  • got to use choices argument in argparse library

Chapter 22

  • motivation behind a named tuple- It would be nice to combine the safety of an immutable tuple with named fields
  • collections module has namedtuple that gives this functionality
  • one can use namedtuple to store all the states of the game and associated error messages and game messages that might crop up as the interactive game progresses
  • TypedDict got introduced in Python 3.8 that has a similar functionality to NamedTuple. However it looks like the former is the preferred option for the author
  • Avoid using global variable unless it is really needed
  • NamedTuple and TypedDict allow you to create a novel data type with defined fields and types that you can use as type hints to your own functions
  • Documentation is a love letter that you write to your future self

Using argparse

  • this module is like a bouncer that allows the right kind of input in to the program
  • the module automatically generates help prompt documentation
  • metavar is the variable that is visible in the documentation
  • the lack of - makes the argument a positional argument instead of a optional argument
  • one can specify a type argument in defining the argument in the parser. This type is a Python data type that the input must be converted to
  • big advantage of argparse type is taking input from command line that are essentially used as numeric values in the program
  • flags are usually optional arguments that do not have value. They can be represented in the parser using store_true or store_false
  • If there is any incorrect input to the program, the parser.parse_args will throw error
  • one can restrict the input values to the program by using choices argument
  • if one needs to specify more than one of a positional argument, one can use nargs argument
  • argparse.FileType('r') is used to specify that the input argument is a file

Fantastic appendix that gave me a good understanding of argparse module


I have been working through this book for the last six days and have had a great learning experience in the process. If I have to list down some of the takeaways, they are

  • pytest module and its relevance to writing any production level code
  • various features of argparse module to validate user input
  • powerful use of regex for searching , splitting, replacing operations on a text
  • confidence that i can code in python and get things done
  • understood the importance of pylint. Every time i run a pylint command on a python program, I will be able to immediately get feedback on the code formatting and style that I have followed