Unit 1 (Review and Programming Practice)

Section 1

  • Why decimal numbers are natural for humans, and why binary numbers are more natural for computers.
  • What is a 0 and a 1 in computer hardware.
  • Properties of, and operations with binary numbers.
  • The Carry, and the Ripple Effect.
  • Review: various types of variables, such as integer (int), real number (float), text string (str), tuple (tuple), list (list), dictionary (dict) etc.
  • Review: checking types of variables using the built-in Boolean function isinstance().
  • Review: generating random integers using the function randint() from the random library.
  • Generating random binary numbers.
  • Review: integer division operator // and the modulo operator %.
  • Converting decimal numbers to binary and vice versa.
  • Addition of decimal and binary integers.

Section 2

  • Properties of, and operations with hexadecimal numbers.
  • Main applications of hex numbers: represent locations (addresses) in computer memory, MAC (hardware) addresses, and color codes.
  • Review: checking whether a given item is present in a list.
  • Using the ASCII table to generate hex numbers.
  • Converting decimal numbers to hexadecimal and vice versa.
  • Hex numbers may contain both lowercase or uppercase characters.
  • Special relationship between hexadecimal and binary numbers.
  • Converting hex numbers to binary one digit at a time.
  • Converting binary numbers to hexadecimal in four-digit chunks.
  • Review: using assertions and exceptions to protect functions against flawed input data.
  • Sometimes, sanity checks may take more lines than the actual function body.

Section 3

  • Transistor count, Moore’s Law, and CPU clock speed.
  • Exploring transistors and logic gates.
  • Using Python to simulate the seven basic types of logic gates: AND, OR, NOT, NAND, NOR, XOR, and XNOR.
  • Practicing safe programming with assertions and exceptions.

Section 4

  • Combining logic gates and simulating simple logic circuits in Python.
  • Simulating the XOR gate using the AND, OR and NAND gates, as well as using the AND, OR and NOT gates.
  • Simulating the Half Adder using the XOR and AND gates.
  • Simulating the Full Adder by adjusting the Half-Adder to be stackable.
  • Simulating the Two-Bit, Four-Bit and Eight-Bit Adders as arrays of Full Adders.
  • Simulating the Full-Adder using the XOR, AND and OR gates.

Section 5

  • Various uses of the underscore character _ in Python.
  • Role of the so-called “shift” in multiplication.
  • Performing multiplication with just addition and shift.
  • Simulating the Four-Bit Multiplier using the Eight-Bit Adder.
  • Simulating the Eight-Bit Multiplier using the Sixteen-Bit Adder.
  • Using the bitwise shift operators <<, >>, <<= and >>= in Python.

Unit 2 (Object-Oriented Programming I)

Section 6

  • Brief history of computers and programming languages.
  • Importance of using well-designed data structures.
  • How did object-oriented programming evolve from procedural programming.
  • Main differences between procedural and object-oriented programming.
  • Classes consist of data (attributes) and functions (methods).
  • An object is an instance of a class.
  • A class can have many different instances.
  • Instances of a class do not share data.
  • Methods are defined on the level of a class but used on the level of an instance.
  • All data types in Python are classes.
  • The so-called “magic methods” in Python and how they work.
  • The bitwise operators & (AND) and | (OR).

Section 7

  • Defining new classes using the keyword class.
  • Using the constructor __init__() to define class attributes and initialize their values.
  • The constructor as well as all class methods must have a mandatory first parameter self.
  • All attributes and methods of a class must be accessed through the prefix self.
  • Adding new methods and new attributes to a class.
  • Instantiating a class.
  • It is a good programming practice in OOP to always access class attributes via class methods (not directly).
  • Using the Sympy and other Math libraries.
  • ‘self’ is not a Python keyword.
  • Creating two training classes: Vocabulary and Number.

Section 8

  • Defining new classes with the keyword class.
  • Using the constructor __init__() to define class attributes and initialize their values.
  • Adding new methods and new attributes to a class.
  • Instantiating a class.
  • Using file operations and working with regular expressions.
  • Not every class needs to have attributes.
  • A class without attributes does not need a constructor.
  • Creating two new classes: Converter and DataMiner.

Section 9

  • Implementing class Line to represent lines in the XY plane:
    • Attributes: startx, starty, angle, length, lw (line width), color, ls (line style).
    • Methods: __init__(), get_endpoint(), set_endpoint(), plot(), get_length(), get_area().
  • Making data structures flexible and open to future development, even though this could mean that they require more memory.
  • Premature optimization is the root of all evil (or at least most of it) in programming.
  • Matplotlib has four different line styles, and how to define them.
  • Objects can be stored in lists like any other variables.

Section 10

  • Using the class Line as a basis to implement class Turtle, a simplified version of the well known Python Turtle Graphics:
    • Attributes: posx, posy, angle, linewidth, linecolor, linestyle, drawing, lines.
    • Methods: __init__(), go(), left(), right(), penup(), pendown(), goto(), back(), set_angle(), show(self), width(), color(), style(), get_length(), get_area().
  • Practicing working with exceptions.
  • Exploring additional useful functions of Matplotlib.

Unit 3 (Object-Oriented Programming II)

Section 11

  • Static methods and when they can be useful.
  • How to derive a subclass from a superclass.
  • When a new subclass should be created, as opposed to modifying the original class.
  • If the superclass has attributes, then the constructor of the subclass must call the constructor of the superclass.
  • Using the function super() to access the superclass.
  • Subclasses can add new attributes and methods, as well as override methods.
  • Importance of a well-designed class hierarchy.
  • What is polymorphism and when it can be useful.
  • What are abstract methods and abstract classes, and when they can be useful.
  • Using the abc (Abstract Base Classes) module.
  • Using ternary conditional expressions.

Section 12

  • Programming practice: Upgrading the Graphics Editor from Python Fundamentals to an object-oriented design (Phase 1).
  • Designing a base class Shape with 6 attributes and 20 methods.
  • Meaning of single and double underscores in the names of class attributes and methods.
  • Review: PEP 8 – Style Guide for Python Code, copying lists via slicing, list comprehension, shallow and deep copying, obtaining memory addresses of Python objects, accessing class attributes via dedicated class methods.

Section 13

  • Programming practice: Upgrading the Graphics Editor from Python Fundamentals to an object-oriented design (Phase 2).
  • Designing and implementing a hierarchy of classes to represent 10 basic geometric shapes.
  • Practicing class creation and inheritance.

Section 14

  • Programming practice: Upgrading the Graphics Editor from Python Fundamentals to an object-oriented design (Phase 3).
  • Designing and implementing class Figure to represent figures consisting of one or more basic shapes.
  • Practicing class creation and inheritance.

Section 15

  • Programming practice: Upgrading the Graphics Editor from Python Fundamentals to an object-oriented design (Phase 4).
  • Designing and implementing three different classes SimpleDrawing, SmartDrawing, and TechDrawing based on three different use cases.
  • Analyzing an example of bad object-oriented programming.
  • In OOP, classes should always work with their own attributes, not with the attributes of other classes.
  • Multiple inheritance, its applications, and its limitations.
  • Multiple inheritance vs. standard inheritance.
  • The Diamond Problem and when it represents a real problem.
  • Mixin classes.

Unit 4 (Selected Advanced Techniques)

Section 16

  • Recursion and its applications.
  • Flattening lists.
  • Polish (prefix) notation.
  • Interactive input.
  • Functions eval() and exec().
  • Variadic functions.
  • Anonymous (lambda) functions.

Section 17

  • Various types of tree data structures.
  • Using recursion to work with binary trees.
  • Iterables and iterators, functions iter() and next().
  • Built-in functions any() and all().
  • Defining custom iterators from scratch.
  • Making iterators via generator functions and generator expressions.
  • Applying maps and filters to data, functions map() and filter().
  • Using the function reduce() for cumulative operations with iterables.

Section 18

  • Using metasyntactic variables.
  • Working with names and namespaces.
  • Creating modules and packages.
  • Using built-in decorators.
  • Creating custom decorators.
  • Writing decorators with parameters.
  • Queuing (chaining) decorators.
  • Decorating class methods.
  • Making Python classes callable.
  • Working with JSON and XML data.

Section 19

  • Overview of the Pandas and Seaborn libraries.
  • Structure of Pandas DataFrames.
  • Entering data into a DataFrame.
  • Creating scatter plots, regression plots, and residual plots with Seaborn.
  • Using the residual plot to justify the linear regression model.
  • Making simple predictions.

Section 20

  • Using Pandas to read files from the hard disk or from a URL.
  • Obtaining the number of rows and number of columns of a DataFrame.
  • Obtaining the list of all column names of a DataFrame.
  • Displaying the beginning and the end of a DataFrame.
  • Other operations with DataFrames.
  • Cleaning data.