Introduction

About Me

My name is Steve. I am a computer science major who is very passionate about programming and computer science in general and I hope to one day obtain a master's degree in either computer science or math. I also love film, fashion, and hiking/camping.

Who This Book Is For

The book is for any one who isn't familiar with coding but with like to begin learning. This book is written specifically with a teenage audience in mind, however any new programmer will benefit form the contents of this book. The book is meant to instill the core concepts of programming using Python, however these concepts can be applied to many other languages and computer systems. Many Python specific things will be glossed over in this book to make it as generally applicable as possible, however, the Python documentation is often linked for further reading.

Book Structure

Every chapter corresponds to a core concept of programming. The order of these topics is mostly ordered in a way that allows for concepts to be built upon one another foundationally. Each section contains examples, diagrams, and most end in a Further Reading section that links to other documents that extend a topic beyond the scope of the book. The second section of the book contains outlines of popular and noteworthy projects that may be worked on to reinforce coding practices and uses. The glossary at the end contains many example programs organized by concepts illustrated. The glossary also contains tables of vocabulary words, definitions, and hotkeys. The first use of a vocabulary words are italicized throughout the book and can be found in the glossary.

Work In Progress

This book is a constant work in progress and is continually being edited and changed.

What Is Programming?

Programming is essentially providing instructions to a system to accomplish a task or receive a result. Everything you see see when you use your desktop computer, laptop, tablet, or phone are all the result of programming. Every aspect of the operation of your electronic devices, even your home appliances like your toaster and fridge, can contain code being executed. Code controls the electricity coursing through the circuitry of a device to to the pixels of a screen that change colors every fraction of a second. Every button click and key press in your favorite app or preferred operating system executes code that someone wrote to interact with other systems someone else wrote to do what that button click does.

Programming involves taking very small and precise steps. But all those steps culminate in every website, video game, operating system, or video you've ever seen on a computer screen. Everyone of those steps add up to programs that are millions of lines long that hundreds of people have worked on and contributed to for decades. However, many programs that have been used for decades are relatively small. Often one person has an idea that they believe will make their or others' lives easier and executes it by writing a program that does that thing. To learn to program it takes understanding that an idea can be realized and the drive to make that idea a reality through learning.

Algorithms

Much of programming involves problem-solving. This is achieved by designing and utilizing algorithms. Algorithms are a set of instructions used to complete a task. The most basic example found in everyday life could be something like following a recipe. And algorithms have been designed and in use since the beginning of human history. The topic of algorithms in computer science and math are very broad, but some examples of tasks that are solved thoguth the study of algorithms are:

  • Sorting
  • Searching
  • Mathematical Proofing
  • Artificial Intelligence
  • Robotics
  • System Load Balancing
  • Networking
  • Multi Processing

Throughout this book, you will learn the programming and computer science concepts to develop your own algorithms to solve problems that arise in your personal programming journey.


Further Reading

Algorithm

Programming Languages

Declarative vs Imperative

Programming is essentially the act of writing something that a computer understands and will have a computer do something based on what is written. The rules by which to write something that a computer understands is called a programming language. There are two overarching types of languages. Also known as paradigms.

  • Declarative Languages
  • Imperative Languages

A declarative language describes how something is, or more technically it defines a state that the computer must reach. A declarative statement in human language could be "The ball is red". Some examples of imperative languages are:

  • YAML
  • HTML
  • SQL

An imperative language offers the instructions or commands to a computer it needs to perform to accomplish a task. An imperative statement in human language could be, "Paint the ball red." Some examples of declarative languages are:

  • C
  • Java
  • Rust

And many programming languages have the capability to be both declarative and imperative. There are many programming languages that have been designed and created in history by individuals, groups, organizations, and corporations all over the world. However, the book will use imperative programming with the programming language Python to teach the basic concepts of programming. By understanding basic programming concepts, the languages you choose to write in will become secondary.

Compiled vs Interpreted

The only thing a computer truly understands is 0s and 1s. Binary code. Also known as machine code or machine instructions. All the code written has to be somehow converted to 0s and 1s. So, along with the languages, programmers also design and create programs used to convert the code to binary. There are two primary ways of converting code to what a computer understands.

Compilers

Compiled languages are languages where the source code of the language is passed to a compiler, which converts the source code to an executable or binary file. Programs are compiled to be run on a specific machine or hardware. Therefore, to be run on another machine, it must be compiled for that machine, and every other machine it is to be ran on.

compilers The path of code from source to executable.

Compiled languages are often used to control hardware itself. Compiled languages are often used for:

  • Robotics
  • Operating Systems
  • Embedded Software
  • Device Drivers
  • Automotives
  • Aeronautics and Aerospace
  • Video Game Engines

Some examples of compiled languages are:

  • C
  • C++
  • Rust
  • Java
  • Go

Interpreters

Interpreted languages are languages where the source code of the languages is passed to an interpreter. The interpreter does not convert the source code to a binary file, but instead runs the source code itself line by line. Therefore, the source code of an interpreted language can be ran on any machine which runs the interpreter. The source code of interpreted languages is often referred to as scripts, and the languages scripting languages. This makes interpreted programs easier to run in more places, this is called portability. And interpreted languages are generally more portable than compiled ones.

interpreters

Source code being given to the interpreter to be ran.

Interpreted languages are often used for:

  • Data Science and Statistics
  • Artificial Intelligence
  • Computing System Administration

Some examples of interpreted languages are:

  • Python
  • JavaScript
  • Shell
  • Powershell
  • Ruby
  • Lua

Why Python?

Python is an interpreted programming language that is commonly used to teach new programmers the basics. This is because Python's design makes it a simpler language to read and write.

Syntax

Syntax is the rules by which something is written. For example, in English adjectives come before nouns; and verbs tend to come before subjects. This is an example of English's syntax. However, in Spanish adjectives tend to come after verbs. This is an example of Spanish's syntax and how human languages can differ in syntax. The same is true for computer languages; the rules of writing something with the same meaning differs between languages. However, once you understand the basic concepts of programming, beginning to learn a new language is only a matter of getting familiar with its syntax.

Portability

Python is portable, as in, the interpreter can be ran in many places, such as a desktop, laptop, phone, or tablet.

Popularity

Python is an extremely popular language that is used across the world by both individuals and large companies and organizations.


This was just an introduction to the different programming paradigms and types of programming languages. There are many more categories languages can be divided and subdivided into. These categories aren't discussed here because they require a more advanced understanding of how programming languages work and are designed.

Python's design is what makes it suitable for both beginners and experienced programmers; and its design is why it is the most popular programming language in the world as of this writing. Next you will learn what programs can be used to actually write code in any given programming language, including Python.

Further Reading

Programming Paradigms

Interpreter

Compiler

Text Editors, IDEs, and PDEs

Ultimately, all the code we write is just text. Instructions that we type and give to a computer to perform. However, there are different kinds of programs we can use to write code more easily, and efficiently.

Features Offered

There are features common to these types of programs that make writing code easier and more efficient. For example:

Syntax Highlighting

Syntax highlighting is a feature that colorizes different parts of the code to make it more easily readable by a human. The code snippets in this book are syntax highlighted.

Code Completion

Code completion is a feature that allows the program being used to write code to auto-complete code being written, or offer suggestions based on the code that you've already written. This is useful for saving time when writing.

Built In Interpreters

Some programs used for writing code allow us to run and test our code in the same program used to write the code. This is useful so we don't have to go to another program every time we want to test or run something.

Plugins

These programs usually support the use of plugins, which are essentially add-ons that add even more functionality.

Text Editors

The most basic kind of program we can use to write code are text editors. There are programs that simply allow us to write and save text files and not much more. A common text editor installed by default in Microsoft Windows is Notepad. A more feature and rich text editor, one designed specifically to write code is *Notepad++". Notepad++ offers syntax highlighting and allows the use of plugins to extend its capabilities. Here is a list of commonly used text editors:

  • Notepad
  • Vim
  • Notepad++
  • Geany
  • Notepadqq
  • Sublime
  • Emacs

Integrated Development Environments or IDEs

The next step above a text editors are integrated development environments or IDEs. IDEs offer everything text editors do and more. IDEs usually offer features that would be found in an entirely other program, and give the programmer the ability to stay in the editor instead of having to switch programs frequently. Some of these features are:

  • Code interpretation or compilation
  • Debugging
  • Version Control

IDEs usually are designed for use with a a specific programming language, however IDEs exist that are used for programming in general. Also, since IDEs are so much more feature rich that text editors, they usually are more complicated and tend to have a steeper learning curve. Some examples of popular IDEs used today are:

  • Visual Studio Code
  • PyCharm
  • Eclipse

Personalized Development Environments or PDEs

There is a lesser known concept of a personalized development environment or pde. This is essentially a text editor that has been customized extensively by installing plugins and other software. So, it is a text editor that has been personalized by the user for their own, specific use. Two editors that are commonly personalized by users are VIM and Emacs.


These types of programs are plentiful and it is common practice to try as many as one likes to find one that suits their preferences and the language they are writing in.

Further Reading

Integrated Development Environment

Installing Python

Windows

The Python interpreter can be downloaded for Windows from the Python's official website.

python Site https://www.python.org/downloads/

Once the installer is downloaded, go to the directory it was downloaded to and execute it.

python file
The Python installer I downloaded to my computer.

Once the installer is launched you will be greeted by this screen: python installer

There are two options when installing.

Admin Privileges

This option should be enabled assuming you are using your personal computer. Admin privileges in Windows generally allow you to install programs and alter specific files. Installing the Python interpreter with admin privileges will allow your scripts you write and run to have greater access to your computer, however this must be done responsibly; or else you may damage your operating system.

Path Variable

This option should be enabled. A path variable is a variable that contains every directory that your user can execute files from no matter what directory the user is currently in. Essentially, when this option is checked, the directory python is installed to will be added to your path variable, so you can execute the interpreter from anywhere.

There are some things installed alongside the interpreter by default like pip. Pip is a Python package manager. It will be discussed at the end of the book in the "And More..." section.

Once the interpreter is installed you will be greeted with a success screen.

python success

Mac

Follow this guide from The Hitchhiker's Guide To Python for installing Python 3.

Linux

On the vast majority of Linux distributions, Python is already installed by default.


Further Reading

Python Download Page

Python docs on Windows Python installation

Command Line Interfaces (cli)

Long before screens or monitors computer system users interacted with the machine using terminals. Initially, terminals were were akin to typewriters. Today, we can still use terminals in our operating systems, however they usually are not literally terminals but terminal emulators.

A terminal offers a mode on interacting with a computer known as a command line interface or cli. The is a textually way of interacting with a computer. Instead of clicking icons to do things the user invokes commands which are just the names of programs a user would like to launch or use. Some commands accept options or arguments which are like settings or inputs the program accepts. Here are the basics of a command line interface.

To access a command line interface you must use a terminal or terminal emulator. There are a wide variety of terminal emulators, such as:

  • Windows Terminal
  • Command Prompt
  • PuTTY
  • Kitty
  • Alacritty

Shells

A terminal emulator will provide you an environment known as a shell. A shell is also an interpreter that is is generally intended to interact with an operating system. Just like Python or any interpreted language, scripts can be written in that shell's language, and its interactive mode is just the shell itself. In fact, Python's interactive mode is a shell. Some popular shells available ans installed by default on many operating systems are,:

  • Powershell
  • zsh
  • bash
  • dash

Prompt

Once a terminal emulator is accessed, you will be greeted by a prompt. A prompt is a method of denoting a new line in a command line interface. They often symbols such as $ or >. Some prompts may also contain, the username, current directory, date, or any other relative system information.

Commands

When at the prompt the user can enter commands. Commands are usually the names of programs that can be started or used from the terminal. For example, if I wanted to launch the windows app "Notepad", instead of finding the icon for the program and clicking on it, I could open a terminal and type the name of the executable: "notepad.exe" at the prompt to launch Notepad. And this is true for any program.

Command Line Arguments

Many command accept command line arguments. This is data or information that can be input into a program. If your program accepts command line arguments they can be list after the name of the program like so:

command argument1 argument2 argument3 ... argumentN

A command will accept as many arguments as it is designed to accept.

Options

Another way to interact with commands at the command line is through the use of options. Options are essentially a program's settings that can be set. Options are also referred to as switches or flags. There are two kinds of options:

Short Options

Short options are options selected by a single letter. For example, tar is a popular program used to archive and compress files. The -x option is the extract option, telling the program to extract whatever file is specified. The file is specified by the -f option. So options can themselves have arguments.

tar -x -f myfile

Now note that short options can be combined into one string for example the following will do the same as the above:

tar -xf myfile

Long Options

Long options are the same as short options except they are longer than a single letter. For example, the tar program has an option called --verbose which allows for greater details while running.

tar -xf myfile --verbose

As you can see short and long options can be used simultaneously. However, not that long options often have short counterparts. In this case instead of --verbose we can just use -v instead.

tar -xvf myfile

Notice that options are often mnemonic, as in, the letter used to represent the option often sounds like part of the option it represents. Like the "x" in "extract", or the "f" in "file". This is by design, but it is not always the case.

Syntax

Command line arguments and options can all be combined to apply settings to a program, give it data, and launch it in one command. For example:

tar -xvzf myfile --overwrite --keep-newer-files

Tar is just one example of a popular command line program. There are countless. However, it is good for demonstrating the general syntax required to call and use programs through commands. In the next section, we will use what we learned about commands to use the Python interpreter at the command line to run our Python programs.


Further Reading

Command Line Interface

Computer Terminal

Shell

Executing Python Code

There are two ways Python code can be ran or executed.

Script Mode

Script mode is where any entire program or script is written from beginning to end and then saved as a file. That file is then passed to the interpreter for the interpreter to execute the script, line by line, from beginning to end.

Write And Save A .py File

For the Python interpreter, the file should be save as a .py file. For example say I wrote a Python script named myscript, I would save this file as myscript.py.

Executing A Python Script

Depending on your preference you can either run your script in an IDE or the terminal.

If using the terminal, the command python calls the interpreter. Now this command takes an argument that is the name of the script file. So, if I wanted to run myscript.py I would make sure I am in the directory that contains the file and type into the terminal python myscript.py and press enter. This calls the interpreter, and gives it my script to run.

Interactive Mode

Interactive Mode is where the interpreter provides a shell or an environment that allows us to execute code as it is given to the interpreter. This mode is generally used for things like quick math or small tests.

Your IDE may provide a window where a shell is visible. Otherwise, to reach the interactive mode you simply type python into a terminal without any arguments and hit Enter. Whether your IDE provides a shell or you reach a shell in your terminal you will see a prompt. A prompt denotes a new line where commands or code will be entered. You should see >>> as your prompt when in interactive mode. From here you can type any Python code you like, and every time you hit Enter, that line, and that line alone, will be interpreted.

What Is Data?

Data is simply information. A computer stores data or information in Random Access Memory (RAM), in secondary storage like a hard drive or solid state drive, or in the Central Processing Unit (CPU). When programming, we are primarily using data that is being stored in memory. All the data in your computer's memory are bits: zeroes and ones. This is all a computer truly knows. The same pattern of bits can be defined to represent different things. Programming languages keep track of where the data is and what is represents. What kind of thing the data represents is known as a type.

An extremely simplified layout of a computer known as the Von Neumann architecture

Data Types

Python has a number of data types that programmers can use to accomplish their task. They are listed below:

NameTypeDescriptionMutableExamples
IntegerintAny integerNo7,10,24,-24,-8564, 103811
Floating Point NumberfloatAny decimal numberNo-73.38, 89.92, 1.0001
ComplexcomplexAny complex numberNo11+7j, -4j
BooleanboolA truth valueNoTrue, False
StringstrA sequence of characters such as a word or sentenceNo"Steve", "Jenny", "I saw a balloon."
ListlistA list or array of the same data objectsYes["Me,"You","Not Them"]
TupletupleA list or array of objects of any differing typesNo("Me","You",1,2,4.8)
DictionarydictA list of key-pair valuesNo"Me":"Yes", "You":"Yes", "Them":"No"
SetsetA list of key valuesyesset([3,5,7])
Frozen SetfrozensetAn immutable setnofrozenset[("me","you)
BytesbytesA byte valuenob'ab\xff'
ByteArraybytearrayA list or array of byte valuesYesbytearray(...)

types

By Максим Пе - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=74062464

Visualizing Objects

Python groups bit patterns into objects. Objects are like boxes, that keep track of:

  • What type of data is inside of it
  • The literal value of the data
  • Its location in memory
  • How often the object is used

An object's type determines what its possible values are and what operations can be performed on it.

Python is known as an object oriented language. Keep in mind that not all programming languages utilize objects. In some languages, the programmer must keep track of the location of data, and what type that data is themselves. Due to the object paradigm, Python is a strongly typed language. In strongly typed languages, the data type of an object doesn't change implicitly. Essentially, data objects are like a box that exists somewhere in the computer's memory. This box contains the data itself, and everything the computer needs to know what that data means and to use that data. In the next section, we'll cover variables, which are used to give names to different objects.


Knowing the different data types a programming language offers allows you to know what ways the language allows you to represent and store information. Since many of the data types Python offers are unique to Python, such as Dictionaries, Sets, and Tuples, we will focus on types that can be found in programming languages more generally. Throughout the book we will focus on the numerical data types, strings, lists, and booleans extensively. In the next sections, we will learn how to name objects of any type using variables.

Further Reading

Data Types

Python Built-in Types

Variables

There are two ways to represent data values in python:

  • Literal Values
  • Variables

Literal Values

Literal Values are the values themselves. If, for example, I type 7 into my python interpreter I am using the literal value 7. If I enter 7+7. I am adding two literal values and will be returned 14.

Variables

Most programming languages allow programmers to assign variables to values. Variables are just names. We give the data names so that we can refer to the variables rather than the literal values. This makes the data easier to follow and change. Python has some restrictions on what variable names can be:

  • A variable may only contain
    • Lowercase letters
    • Uppercase letters
    • Digits
    • Underscore
  • Variables are case-sensitive.
  • A variable may not begin with a digit
  • A variable may not be a reserved word. Reserved words may be found using the command:
help("keywords")

Assignment

Variables can be assigned values using the assignment operator: =, with the variable name on the left and the value on the right. Operations will be covered in the next section. But for now know that in most programming languages = does not mean "equal to" or "is". It is an action that can be thought as "make" or "make equal to".

For example,

a = 7

could be said in words as "make a 7", "make a equal to 7", or "let a be 7".

And now if a is put into the interpreter it will return 7 because a is now 7 and will be treated as such.

Variables and Objects

Recall that in Python all data is organized into objects to help keep track of the data and what the data represents. When we apply our knowledge of Python objects, to what we know about variables and assignment, we can detail what's actually happening. In our previous example we assigned the variable name a to the integer object 7. Let's extend our previous example and assign something to a.

a = 7
b = a

If you recall the transitive property from mathematics you know that if a is 7, and b is a then b is also 7. Now what if we change a from 7 to something else or in other words reassign a?

a = 7
b = a
a = 11

What do you think is now the case? Since a is changed is b now changed as well? The answer reveals something important about variables and objects in Python.

References

In some programming languages the variable name is a location, in other words, in those languages a variables name is the name of a place that contains the data. Python IS NOT one of these languages. In Python variables are references. They refer to or point to a data object. These types of variables are sometimes called pointers.

var1

Diagram of our variable names pointing to different objects

In short, in Python variables are only names. When you assign a variable, you are simply naming some data object.

Let's return to our previous example:

a = 7
b = a
a = 11

In this Python code snippet, the following occurs:

  1. a is pointed to an integer object with a value of 7.
  2. b is pointed to the value that a point to (7).
  3. a is pointed to a new integer object with a value if 11.

var2

So, if you enter b into the interpreter, it will return 7. This is because when you assign b to a, you are simply giving the object 7 two different names: a and b. In other words, you are point b to the same data object a is pointing to. Then, when a is assigned to 11, it is being pointed to a new data object, but that does not change what b is pointing to, so b remains 7.

Variable Naming Conventions

Outside of the Python keywords and rules we can name variables whatever we please. But what is a good variable name. In larger programs, good names are important to keep the code readable. So you, or another person unfamiliar to the code can easily read, understand, and follow it.

Your variable names should be:

  • Brief
  • Descriptive
  • Unique

A common variable naming convention used is called camelCase. camelCase separates multiple words in a name by capitalizing the last word of the variable name. Another common convention is snake_case. Where the words in the name are separated by underscores. snake_case is commonly used in Python but both camelCase and snake_case will be used in this book.


This section introduced variables, which in Python, are names or references to objects. In the next sections operations that can be used on variables, and thus objects, will be introduced.

Further Reading

Variable

Arithmetic Operations

Arithmetic Operations

There are a number of operations in mathematics we can use to calculate values using numbers. These are arithmetic operations. The arithmetic operations available to use in Python are listed below:

OperatorDescriptionExampleResult Returned
+Addition7+714
-Subtraction70-169
*Multiplication7*749
/Floating-point division7 / 23.5
//Integer or Truncated Division7 // 23
%Modulus or Remainder of Integer Division7 % 31
**Exponentiation7 ** 249

These examples are performing the operations on literal values as in the objects themselves not variables. Operations can be performed on both literal values and variables. Her are more examples:

Addition and Subtraction

>>> a = 6
>>> a + 4
10

Addition and subtraction works as expected. Note the use of both literal values and variables. And we can include as many operands as possible. An operand is any object being operated on by an operation.

>>> 7+10-2+11-14+a
18

Multiplication

Multiplication is similar. For example:

>>> 10*7*15*5
5250

Division

Division is a different story since there are different styles. There is floating point division: /. And division with truncation: //. Truncation is just removing everything after the decimal point. Truncating is essentially just rounding down to the nearest integer in the case of positive numbers and rounding up in the case of negatives.

Floating Point Division

Floating point division is division that will return the answer of division including if it is a floating point (a decimal number). For example:

>>> 7.5 / 2
3.75

Division With Truncation

Truncation will remove everything after the decimal point. It is essentially rounding or removing any remainder. For example:

>>> 7.5 // 2
3.0

Modulus

Modulus or mod for short simply returns the remainder of division. For example:

>>> 7.5 % 2
1.5

Exponentiation

Exponentiation is raising a number by an exponent. The number being raised, or the base, goes on the left. And the exponent is on the right. For example:

>>> 3 ** 2
9

Assignment Operators

Assignment operators are operators that allow us to both conduct an arithmetic operation on a variable and assign the result to the variable with a single operation. In other words, the arithmetic operation and assignment operation are combined into one step.

The assignment operators found in Python are listed below

OperatorDescription
=Assigns value to variable
+=Adds value and assigns result
-=Subtracts by value and assigns result
*=Multiplies by value and assigns result
/=Divides by value and assigns result
**=Raises by power and assigns result
%=Computes modulus between value and assigns result
//Floor divides by value and assigns result

Not every operator will be given an example for the sake of brevity, but the concept is the same for all. Let's use multiplication for our example. Consider:

>>> myNumber = 7
>>> myNumber = myNumber * 7
>>> myNumber
49

Here myNumber is assigned to 7. Then it is assigned to itself times 7 which is 49. And when returned it is now assigned to 49. Where it is being assigned to itself times 7 can be combined into a single operation with an assignment operator.

>>> myNumber = 7
>>> myNumber *= 7
>>> myNumber
49

The result of this code block is the same, however the multiplication and reassignment of myNumber is combined into the *= operator.


This section described Python's arithmetic operations. To see more examples of these operations in use check the appendix. The next section will cover logical operations.

Further Reading

Arithmetic Operations

Logical Operations

What is Logic?

Logic is a kind of math that is likely different than what you are familiar with. Logic is used to determine whether something is true or false. And operations in logic don't use numbers, but only truth values. As in, true or false. Recall, that computers can only truly understand 0s and 1s. Naturally, logic is applicable to the design and study of computers. Since there are only two possible values, 0 can be thought of as false, and 1 as true. And using logic, outcomes can be mathematically calculated within the circuitry of a computer the same way we determine whether something is true. In our case, we will use logic to calculate whether somethings is true, or if certain conditions are met, in our code.

Truth Tables

Before we discuss the operations themselves, we must first discuss truth tables. Truth tables are used to describe the output of an operation given the truthfulness of the inputs. Truth tables are a good way of visualizing the way the operations work and what to expect when they are used. A truth table is a table with a column for each input and a column for the output. The table demonstrates every possible combination of inputs and the output each combination gives.

Booleans

Recall that booleans are a data type that only have two possible values, True or False. Logical operations can only be performed using Boolean values. It is common for truthness to be represented as 1 and falseness with 0. And in Python, either the word or numerical representation may be used; the following examples will demonstrate this.

Operations

There are three logical operations we will use are AND, OR and NOT. Each operation will be discussed and a truth table for each will be provided. Keep in mind that the logical operations we will discuss are communicative like addition or multiplication. As in, the order the inputs are given does not change the output.

AND

AND is an operation that accepts two inputs and the output is only true when both inputs are true. AND is also known as a conjunction. Here are some examples in Python:

>>> True and False
False
>>> 1 and 0
0
Input 1Input 2Output
111
100
010
000

An AND truth table

OR

OR is an operation that accepts two inputs and the output is true whenever at least one of the inputs in true. Or is also known as a disjunction. Here are some examples in Python:

>>> True or False
True
>>> 1 or 0
1
Input 1Input 2Output
111
101
011
000

An OR truth table

NOT

Not is an operation that accepts one input and the output is the opposite of the input. This is known as negation or inversion. Here are some examples in Python:

>>> not False
True
>>> not 0
True
Input 1Output
01
10

A NOT truth table


Further Reading

Logic in Computer Science

Precedence

You may be familiar with the order of operations in mathematics; sometimes referred to as PEMDAS. This is a system that describes the precedence of operations in math. Programming languages have a similar convention. Without grouping symbols such as parentheses, operations will be conducted in their order of precedence. An operation with a higher precedence will be conducted before an operation of lower precedence if their precedence is not overridden by grouping symbols. Note that operations with the same precedence will be evaluated from left to right as they appear.

The following table lists Python's operations in order of precedence from highest to lowest.

OperationName
()Parentheses
**Exponentiation
*, /, //, %Multiplication, Division, Floor Division, Modulus
+,-Addition, Subtraction
<, <=, >, >=, !=, ==less than, less than or equal to, greater than, greater than or equal to, not equal, equal
notBoolean NOT
andBoolean AND
orBoolean OR
=Assignment

Functions

In programming, a function is code that accepts an input and returns an output. What the function accepts is called a parameter. A function can have as many parameters as needed. Generally, a function takes parameters, does somethings with them, and returns something based on what the parameters were. Running a function is referred to as calling a function or a function call. Based on the function's definition, it will only accepts parameters of specific data types, in a specified order. Furthermore, a function will only return data of the type it is defined to.

Syntax

In Python, and many other programming languages, calling a function has the following syntax: functionName(). The name of the function followed by a parenthetical. Within the parentheses goes the parameters. The parameters are ordered and separated by commas. Let's look at some commonly used functions that are already built into Python.

print()

In the famous "Hello World!" program, we use the print() function.

print("Hello World!")

Here, the print() function accepts a single parameter, a string to be printed.

input()

Another commonly used function is input(). This function also takes a single parameter: the string to be displayed to the user prompting the user to input data.

Pass By Value vs. Pass By Reference

There two ways data can be provided to a function. By value or By reference.

By Value

Some programming languages pass data to functions by value. This means that the only the value and not the object itself is provided to the function. Essentially, the function creates a copy of the variable for use within the function. So if the function changes the variable, the true original variable will not be changed.

By Reference

Python passes objects to functions by reference. Recall that variables in Python are references or pointers to objects. It is not a copy. This means that if a function changes the value of any object that was passed to the function, its value will be truly changed. For example:

>>> listA = [0]
>>> listB = listA
>>> listA = [0,1,2,3,4,5]
>>> listB = listA
>>> listB.reverse()
>>> listB
[5, 4, 3, 2, 1, 0]

listB was reversed and this is demonstrated but knowing that variables in Python are references and that listB was passed to reverse() as a reference to an object; what do you believe listA is now?

>>> listA
[5, 4, 3, 2, 1, 0]

listA was reversed as well! Because listB and listA are references to the same object.

is Operator

The is operator accepts two input variables and returns a boolean. If the variables reference the same object is will return True otherwise, it will return False.

>>> listB is listA
True

listB and listA are references to the same object, so is returns True.


Further Reading

Python Built-in Functions

Methods or Dot Functions

A data type defines what operations can be used on that type and what methods or dot functions exist for objects of that type. These concepts will be covered more deeply near the end of the book, but for now know that this essentially means that the designers of Python designed functions for every data type to be manipulated. We will focus on the string and the list data types. We will use the built in functionality that Python offers to manipulate these data types.

Dot Function Syntax

A dot function is a function that operates on an object of a specific type or class. They are also referred to as methods. The syntax of calling a dot function is appending a dot to the end of an object followed by the function name and a parenthetical:

object.functionName()

The function takes the object as an input, and outputs something based on the input and the function's definition. Remember that the function must be for the data type of the object. Again, we will be using methods that are built into Python by its developers for use on its data types.

Strings

Concatenation

The + operator not only works for numbers but also strings. When two strings are "added", the string on the right will be appended to the one on the left. This is known as concatenation.

For example:

>>> x = "hello"
>>> y = " world! "
>>> x+y
'hello world! '

Here the string y is appended to the string x.

Capitalization

Now say I need to capitalize every word of this sentence. We can use the .title() function to accomplish this.

>>> x = "hello"
>>> y = " world! "
>>> (x+y).title()
'Hello World! '

Strip Whitespace

Now say I want to remove the whitespace I left at the end of the string. Whitespace is any space that isn't text such as a Space or Tab. The .strip() function does this.

>>> x = "hello"
>>> y = " world! "
>>> (x+y).title().strip()
'Hello World!'

Note that dot functions can be listed one after the other. They work in order from outside in. In other words, from right to left.

>>> x = "hello"
>>> y = " world! "
>>> z = x + y
>>> z = z.strip()
>>> z = z.title()
>>> z
'Hello World!'

Here the same is accomplished by assigning x+y to z and using the functions on z one at a time. The main difference between these two ways is that some would say one is more readable by a human than the other. Depending on the context this may be true.

Lists

Python contains numerous built in methods for manipulating lists. Say I have a list of numbers 1 - 10:

>>> myList = [1,2,3,4,5,6,7,8,9,10]

Append

The .append() method will add a new object to the end of a list. I will continue the pattern and add 11.

>>> myList = [1,2,3,4,5,6,7,8,9,10]
>>> myList.append(11)
>>> myList
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Pop

The .pop method will remove or "pop" the first last object out of the list.

>>> myList.pop()
11
>>> myList
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Reverse

The .reverse() method reverses the order of all elements in a list.

>>> myList.reverse()
>>> myList
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

This section is just a small taste of the different built-in methods Python has to offer. Every data type has a number of methods available for use. The list of methods used and discussed in this book is by no means exhaustive. Refer to the Python documentation for more information. Links to some of the documentation are below.

Further Reading

Python Docs on List Methods

Python Docs on String Methods

Type Conversion

Python gives us the ability to convert some data from one type to another, depending on the types. This is known as type casting.

This is can especially useful when getting user input. Recall, input() which allows us to obtain input from a user. Say we want to get two numbers from the user to be multiplied together.

x = input("Enter First Number:")
y = input ("Enter Second Number:")
z = x * y
print(z)

If you run this code and provide numbers you will recieve an error. This is becuase the numbers provided are strings. input() returns strings and strings can't be multiplied. What input() returns must be casted to an integer. The function int() does this.

x = input("Enter First Number:")
y = input ("Enter Second Number:")
z = int(x) * int(y)
print(z)

The code now works! x and y are each casted to ints before they are multiplied so there is now no error.

Nesting

This code can be made a little cleaner if we know that functions can be nested. Nested means "inside one another. Essentially functions, and other structures in most programming languages can be nested. When functions are nested, they run from the inside out. In other words, when nested the innermost function will execute first, then the one directly above it, and so forth.

x = int(input("Enter First Number:"))
y = int(input ("Enter Second Number:"))
z = x * y
print(z)

This code has the same functionality, however it nests the calls to the input() function with the int() function.This could be further compacted by not assigning what int returns to variables.

z = int(input("Enter First Number:")) * int(input("Enter Second Number:"))
print(z)

This code has the same effect has the other two examples, except here less variables are used. These are examples of style. Recall that styles is subjective and whether one stylistic decisions is better than another is up to preference. However, the ulimate goal is to balance: efficiency, readability, and elegance.

Implicit Type Casting

The casting thus far has been explicit. As in, we called a function that casted an object to a data type we needed.However, the interpreter often casts types itself without any intervention. This is known as implicit casting. For example, implicit casting occurs when doing arithmetic with object with differing types.

>>> x = 7.7
>>> y = 7
>>> type(x)
<class 'float'>
>>> type(7)
<class 'int'>
>>> z = x+y
>>> type(z)
<class 'float'>

Here it is demonstrated that adding a float and an int results in the interpreter casting the result to a float.

Commenting

What Is A Comment?

A comment is simply text in code that is ignored by the interpreter that gives the human reading the code more information. A comment isn't meant for the computer at all, only for humans reading the code.

When To Use Comments

Comments should be used to make what your code does clearer to the reader. Good uses of comments include:

  • Explaining what a variable is for
  • Explaining what a function does
  • Dating changes
  • Leaving notes of what still needs to be done or changed

How To Comment

In most programming languages including Python there are two types comments single-line and multi-line.

Single-Line Comments

A single line comment is a comment where the interpreter will only ignore the line of text denoted as a comment. In Python, a single line comment is denoted by #. For example:

# This is a comment. 
print("Hello, World!")
# This is another comment

Multi-Line Comments

A multi-line comment is a comment where multiple lines are denoted as being comments. Using a multi-line comments is good for larger blocks of comments like paragraphs. Multi-line comments in Python are denoted by, """. Multi-line comments must be opened and closed. In other words, the first will denote the beginning of the comment, and another will denote the end. For example:

""" Everything	
between
is
as
comment.
"""
print("Hello, World!")

Comparison Operators

Before conditionals we must first learn to use comparison operators. Like logical operators, comparison operators return Booleans. Comparison operators compare two operands. One on the left and one on the right. If the comaprison is true, the operation returns true. If the comaparison is false, the operation returns false. There are a number of comparison operators available to use in Python. The following table describes them:

NameOperatorDescriptionExample
Equality==Check if operands are equal2 == 2
Inequality!=Check if operands are not equal4 != 2
Less Than<Check if left operand is less than right operand2 < 4
Less Than or Equal<=Check if left operand is less than or equal to right operand6 <= 7
Greater Than>Check if left operand is greater than right operand8 > 4
Greater Than or Equal>=Check if left operand is greater than or equla to right operand7 >= 3

What Is a Conditional?

A conditional statement is one where something is true based on, or under the condition that, something else is true. Sometimes conditional statements are referred to as if statements.

Conditionals In Human Language

Conditional statements exist in human language. For example:

If I get a birthday gift, I will be happy.

In this statement, I am happy IF I get a birthday gift. I am happy under the condition that I get a birthday gift. Examples in human language can be useful in understanding the concept of a conditional.

Conditionals In Programming

Conditional statements are very often used in programming. We use them so that certain code will only execute if something is the case. So if it isn't the case, the code won't execute. Recall the boolean data type. Booleans are either true or false. In programming we use Booleans to represent the truthfulness of a condition.

Condition & Body Structures

Any structure involving conditions in Python - and most programming languages in general - follows the same basic formatting.

  1. A condition is checked
  2. If the condition is true, the body executes. The body is the code block that will execute if condition is true.

if

Flow chart illustrating conditionals

Conditional structures in Python have a specific syntax like all programming languages. In Python:

  • The line of the conditional statement is ended with a colon: :.
  • Every line of the body is indented

Indentation is very important in Python. In Python indentation is how the body of certain structures are distinguished form other parts of the structure by the interpreter.

if statements

If statements are one of the most basic structures of programming that we will often use. An if statement executes code based on whether a given condition is true. Here is an example of a basic if statement in Python:

if (True):
    print("Hello World!")

Using this specific example we can note things about the syntax of an if statement specific to Python:

  • The if statement is began with the if keyword.
  • The condition to be checked is enclosed in parentheses
  • The line of conditional statement is ended with a colon
  • Every line of the body is indented

In this specific example the the body will always execute since True is always true. The next example will have a more complicated condition:

x = 10
if ( x > 21 ):
	print("x is larger than 21")

In this case, the body does not execute. Try replacing x with a larger number, so that the body does execute.


Further Reading

Conditional

Else Statements

Control Flow

Say you've written a program that contains an if statement. But you would like the program to so something else if the if statement's condition is false and the if statement's body does not execute. This is known as control flow. Control flow is the control of the order of execution of code in your program. By using conditional statements of different kinds we can control what happens based on these conditions.

else statements

The conditional statement we can use to execute code if the body of an if statement does not execute is an else statement. An else statement checks a condition following an if statement if and only if the conditional of the if statement was false and the if statement did not execute its body.

Say we would like to continue the example from the previous section by having the program do something else since the condition of the if statement is false.

x = 10
if ( x > 21 ):
    print("x is larger than 21")
else:
    print("x is 21 or smaller")

Here an else statement comes directly after the if statement. The else statement's body is print("x is smaller than 21"), and it will execute since the body of the if statement does not. Note that an else statement has no conditional check. However there is technically an implicit condition: that the condition of the if statement is false. Because an else statement will not execute its body if the if statement has already executed its.

else The flow from an if statement to an else statement

else if statements

The elif statement - short for else if however, is an else statement with a condition. So it executes its body if the previous if statement did not execute its body AND the elif statement's condition is true. So, where a if-else block can be used for 2 possible outcomes, an if-elif-else block can be used for 2 or more possible outcomes. Keep in mind that if the if statement executes its body, nothing else is done. The flow stops at the if statement if it has a true condition.

elif

The flow from if to elif to else statement

x = 19
if ( x > 21 ):
    print("x is larger than 21")
elif (x > 14):
    print("x is larger than 14")
else:
    print("x is 14 or smaller")

Here, the value of x is checked twice before the else statement finally executes. This structure could be extended using as many elif statements as necessary.

Nesting

Just like functions, conditional statements can be nested as well. Recall nesting means to contain one structure within another. For example:

x = "Hello"
y = " World!"

if (x == "Hello"):
    if (y == " World!"):
        print(x+y)

Here the body of the next if statement executes since the inner condition and outer condition are both true. Not that this is logically the same as ANDing the conditions in a single if statement since BOTH conditions must be true.

x = "Hello"
y = " World!"

if ( x == "Hello" and y == " World!"):
    print(x+y)

Further Reading

Control Flow

Python Docs on Control Flow

Switches

Another conditional structure in programming are switches. Recall, that another word for options on the command line are switches. A switch structure is how options are often implemented in programs.

A switch essentially falls through a series of conditions, in order, until one is true. When it is true, the body of that condition is executed, and the switch exits. If no conditions are true, the switch either executes a default case or exits doing nothing.

switch A diagram of an example switch statement

In Python switch structures can be used for pattern matching, as in, comparing strings and seeing if they are the same. A switch is began with the match keyword followed by what is to be matched. This line is ended with a colon.

match "fav_food"

Then each case follows. The keyword case begins each line. Followed by what is to be checked for. These lines are indented ended with colons. Each case is then followed by an indented body that executes if the condition is true. If it is false, the switch falls through to the next case.

    case "pizza":
        print("Pizza is my favorite food too!")

An example script will be provided that asks a user what they're favorite food is. The script uses a switch to check against known foods. It will return a statement to the user based on what the given food was.

fav_food = input("What is your favorite food?\n")

match fav_food:
    case "pizza":
        print("Pizza is my favorite food too!")

    case "cake":
        print("Cake is my favorite food too!")

    case "pie":
        print("Pie is my favorite food too!")

    case "sushi"
        print("Sushi is my favorite food too!")

    case _:
        print("I've never had " + fav_food + " before, but is sounds good!")

Note that the default case, the last case, is denoted by an underscore: _. The body of the default case will execute if no other case is true.


Further Reading

Python Docs on match

Switch Statement

While and Do-While Loops

The other, if not the most, fundamental structure in programming are loops. A loop checks a condition and executes the body, then rechecks and executes the body, until the condition is false. Each time the loop executes the body is call an iteration. The loop will iterate until the condition is false.

While Loops

While loops are the simplest form of loops. Per the name, while loops iterate while their conditions are true and until they are false. Once the condition is false, the loop exits and moves on to the next code. while The flow of a while loop

For example:

while(True):
	print("true")

This code is an infinite loop. It will iterate and print "true forever, since the condition is never false. Not very useful. Let's try a while loop with a changing condition.

Loops are necessary for developing a process that require doing the same action multiple times. Like printing. Say I want to print every number from 0 to 1. I can do this with a while loop.

n = 0
while(n <= 10):
    print(n)
    n += 1

This script:

  1. Assigns n to the integer 0.
  2. Begins a loop that will execute until n is 10.
  3. Prints n.
  4. Increments n by 1.
  5. Repeats until n is 10.

Let's try another example: Say I want to write a program that prints every multiple of 2 from 2 to 20. We can do this with a while loop.

n = 2
f = 1
while(n * f <= 20):
    print(n * f)
    f += 1

Another way to accomplish this to to simply check if a number is even, since all multiples of 2 are by definition even. This code takes advantage of the modulo operator and an *if * statement.

n = 1
while(n <= 20):
    if ( n % 2 == 0 ):
        print(n)
    n += 1

This code checks every number form 1 to 20. If the number is divisible by 2 it prints, if not nothing happens and the next number is checked.

Continue and Break

Python supports two keywords that allows us to stop a loop from iterating again or command a loop to jump to the next iteration.

Break

The break keyword causes a loop to immediately exit. break statements should be used only when necessary as when using them instead to end a loop instead of allowing the loop to end naturally based on its conditions can be considered bad style. However while loop utilizing break is often used to accept user input.

while (True):
    meals = int(input("How many meals did you eat today?\n"))
    if meals >= 0:
        break
if (meals == 0):
    print("You should eat something today!")
else:
    print(meals," meals sounds ok.")

This code utilizes an infinite while loop. The loop will iterate and ask the user a question over and over until the number they provide is positive. If they give a positive number, the loop breaks. This is to ensure the user provides usable information.

The next section will cover the more widely applicable and succinct looping structure, the for loop.


Further Reading

While Loops

Python Docs on while

For Loops

Before we discuss for loops we must first understand more about about collection types. Collection types are data types that hold multiple objects such as strings, lists, tuples, and dictionaries. We will focus on strings and lists in this reading since these data types are not unique to Python. However, these data types are all iterable types.

Iteration

Collection types in Python, other than a set, are ordered. One object by the other. Each space within a collection is called an index. To iterate over a collection type is to enter the indices one after the other. Every iteration may simply check whats inside, maybe the contents of the indices are altered or used. You may already be able to tell, that a loop structure would be perfect for this. A loop can doing something with a index every iteration until there are no indices left. Keep in mind that Python, like many other languages employs zero based indexing. This means that the indexing number begins at 0 not 1.

array_1d A diagram of the indices of an iterable collection type such as a list or string.

For Loops

The kind of loops used for iterating over collections are for loops. Many programming languages have for loops. A while loop is logically the same as a for loop, however the aspects that would need to be added to a while loop, such as a counter to keep track of the current index, are built into the design of the for loop. A for loop in Python may also be used to iterate over a range of numbers. The syntax of for loops in Python is particularly nice compared to other languages, and this is mostly due to the in operator.

in operator

The in operator checks whether a given value is within a collection. If the value is in the collection, the operator will return True if not it returns False. For example:

>>> name = "Steve"
>>> 's' in name
False
>>> 'a' in name
False
>>> 'e' in name
True
>>> 't' in name
True

Syntax

In Python, the for keyword can be combined with the in operator to create a loop. Here is the general syntax:

for variable in some_collection:
    body
  • The for keyword begins the loop.
  • This is followed by a variable name. The variable will reference the current element.
  • Then the in operator followed by the name of a collection indicates what collection or range is going to be iterated over
  • This line is ended with a colon followed by the indented body that will execute every iteration.

Let's look at an example that iterates over a range. Iterating over a range is good when something needs to be done a specific number of times. So here a for loop is not necessarily being used to iterate over a collection.

for i in range(1,10):
    print("This is the iteration number " + str(i))

Here a line is printed every iteration. Note that this only iterates 9 times, because the loop ends once 10 is reached, so the body does not execute on 10. Also note that the variable i represents the element of the current iteration. i is known as a counting variable and is often used as a placeholder variable in for loops and loops in general.

Now let's try a loop that iterates over an actual collection.

pets = ["dogs","cats","fish","horses","pigs","hedghogs","ferrets"]

for pet in pets:
    if pet == "pigs":
        print("I want a pet pig!")
    else:
        print("I don't like " + pet)

This loop checks every element in pets and if if is "pigs" a special sentence is printed. If not the current element is used to print another sentence. Note that this example utilizes nesting. The conditional if statement is nested within the for loop. Loops can also be nested within other loops.

Nested For Loops

To understand nested loops we first must understand the kinds of structures they are intended to iterate over.

Consider that the visualization of a list is a straight line. One index after the other. What if we had a list of lists? The visualization would resemble something like a checkerboard or grid.

array_2d A visualization of a two dimensional list

Every element of the our original list is now within a row. And every element of the row has a column associated with it. This is known as a two dimensional list where our original list was a one dimensional list. Being a two dimension list mean that every iteration of a a element of the row involves iterating over every element within the column for that position in the row. And to do this we must use a nested for loop.

food = [["eggs","biscuit","grits","bacon","jam"],["pizza","sandwhich","salad"],["steak","asparagus","toast"]]
for meal in food:
    for item in meal:
        if item == "asparagus":
            print("I love asparagus!")

This code iterates over the list of lists food by iterating over and assigning every list within to meal. Then meal is iterated over assigning every element in meal to item before meal is reassigned to the nest list. This accomplishes checking every element within every list for "asparagus".

This concept can be extended to any number of dimensions. In other words, any number of lists within lists. And for every dimension another nested loop will be added.

array_3d

Visualization of a three dimensional list.

For example, a three dimensional list would be a list within lists within lists. And so forth. However, anything beyond 3 dimension is seldom used, and even three is usually reserved for programming involving more advanced physics and math. Furthermore, Python is generally not suited for nested looping has it is too computationally intensive for interpreted languages.


Further Reading

Python Wiki On For Loops

For Loop

User Defined Functions

We've used functions throughout or code. Whether they were functions or more specifically methods or dot functions, they were functions designed and written by the Python authors for our use. But what if we want to write our own functions? Most programming languages, including Python, support user defined functions. So we can define and use our own functions!

Writing your own function has many benefits like:

  • Easily using the same code in multiple places
  • Using code in other scripts or programs
  • Sharing code with others

Syntax

In Python, the def keyword denotes the beginning of a function's definition. The definition of a function is essentially the code that is what a function does. def is followed by the function's name and and immediately by an open and closed parenthetical. Inside the parenthetical will go your function's parameters. However, your function does not have to have parameters. Every line body of the function is indented. The body is what the function will do every time it is called.

def square_user_input(): 
     user_int = float(input("Give me a number\n"))
     print(user_int ** 2)

This example defines a function named square_user_input(). It takes no parameters. It squares a number given to the interpreter by the user, and prints that number. But this code currently does nothing. The function is defined but it needs to be called to execute, like every other function we've been using.

square_user_input()

This code will call our function which executes it.

Parameters and Returns

What if I want to write a function that takes parameters and returns an object? As in, accepts inputs and return outputs. This can be easily done. For parameters, we use variables to refer to the parameters that can be given to the function, in order. For example,

gcf(num1, num2):

Begins the definition of a function named gcf() that accepts to parameters. When given, the parameters will be assigned to num1 and num2 in our code. However, those variables will only exist inside the function definition. This is an example of scoping. Scoping refers to what data areas of the code is aware of. By default, the scope of variable parameters, and variables defined within function definitions can not be used outside of the function. This data is said to be out of scope for the rest of the code. Likewise, variables defined outside the function are out of the scope of the function's definition. The global keyword can be used to make a variable's scope the entire script, so it can be used everywhere. However, the use of global is not recommended as it is often not necessary and should only be used when absolutely necessary.

This example function is named gcf() for greatest common factor. It will return the greatest common factor of two positive numbers.

def gcf(num1, num2):
    if (num1 == num2):
        return num1
    elif (num1 < num2):
        for factor in range(num1, 0, -1):
            if (num1 % factor == 0 and num2 % factor == 0):
                return factor
    else:
        for factor in range(num2, 0, -1):
            if (num1 % factor == 0 and num2 % factor == 0):
                return factor

Again this function is defined to accept two parameters, however there are multiple uses of the break keyword. This keyword returns an object and immediately exits the function. So, in this function, the return keyword is used to output the largest factor of the two numbers once it is found and exit the function. Remember, this is just the definition. Let's actually call and use the function in a script.

user_input1 = int(input("Please enter a positive integer\n"))
user_input2 = int(input("Please enter another positive integer\n"))

gcf = (gcf(user_input1, user_input2))
print("The greatest common factor between these two numbers is:", gcf)

This code snippet uses our function to get the input from the user, uses their input as parameters, and prints the greatest common factor to the user. If these two code snippets are in the same script, I can use the function I defined anywhere in the script, because the function will be in scope for the entire script. But what if I want to call a function that is defined in another file? Or I want to use a function someone else wrote? These possibilities will be discussed in the following sections.


Further Reading

Python Docs on Defining Functions

Modules & Imports

In many programming languages, including Python, it is possible to use source code located in other files in your own code. This source code often includes objects such as data types and functions that can be brought into scope. As in, the interpreter will be made aware of this code and can be referred to and used. The import keyword is how other code can be brought into scope.

import

The import keyword should be used at the beginning of your code to denote what to include for interpretation. But what exactly can be imported?

Modules

A module is a a Python script like the ones we've been writing. It's a text file ending in .py that contains Python source code. However, a module is primarily source code containing definitions, such as the definitions of variables or functions. When this file is imported the definitions of these objects are brought into scope and can be used. Importing is usually used if you have functions you wrote, but you want to use them in multiple other scripts. By importing, you don't have to include the definition in every different script you use the function in. More generally, if your script because very large, you can simply split the different parts of one script into many different ones and import them into a single script that is interpreted.

Packages

A package is a kind of module. Essentially, a package is just a module that contains many other modules or packages. It's like a bundle of modules packaged up into one that can be imported.

Example

Recall the example from the previous section. There was the definition of the function gcf() which returns the greatest common factor of two positive integers. Say this definition is in a file named greatest_common_factor.py. If I want to use this function in another file, I must import it by using the import keyword followed by the path to the file or module. Recall that a path is the location of the file. Assuming that the module is in the same directory as the script I'd like to import the module to, the following line can be placed at the top.

import greatest_common_factor.py

Now the function can be used, however the syntax for calling a function that was imported is particular. The syntax to call a function that was imported is to append the name of the function to the name of the module with a dot like so:

moduleName.functionName()

So for our script we can call gcf() like this:

greatest_common_factor.gcf()

Importing Individual Functions

Python supports importing individual functions from a module so the entire module doesn't have to be. For example, if we wanted to just import the function gcf(), and not the entire module, out import statement could be the following:

from greatest_common_factor import gcf

This code uses the from keyword to specify the module name then import follows to specify the function name.

Module Aliases

Furthermore, modules can be renamed, so using them in the code is more convenient. For example, to import greatest_common_factor.py and rename it to gcf our import statement would be the following:

import greatest_common_factor as gcf

The as keyword specifies what to rename the module to. So now to call an imported function the module alias can be used like so:

gcf.gcf()

Python Standard Library

The Python Standard Library is a libray of modules that are usually installed onto a system along with the interpreter. So we should have access to them alreay, they do not need to be downlaoded or installed. Standard modules are official and designed, written, and backed by the Python developers for our use. Noteworty standard modules are listed in the table below:

ModuleDescription
mathProvides mathematical functions
cmathProvides mathematical functions for use with complex numbers
datetimeProvides clocks and counters
randomProvides generation of random numbers and values
osProvides tools for interaction with the operating system
ioProvides tools for reading and writing to files

Keep in mind there are countless modules and packages available for install outside of the standard libray. Those modules are developed by third parties and some are incredibly popular. Refer to the later section on the package manager pip to learn about installing non standard Python packages that can be imported for use in your own scripts!


Further Reading

Python Standard Library

Python Docs on Import

Python Docs on Modules

Python Docs on Packages

Defining and Using Classes

Object Oriented Programming (OOP)

Recall that Python is an object oriented programming language. This means that all data is organized by certain properties and attributes which define the object such as:

  • Accessible Data
  • Applicable Operations
  • Methods or Dot Functions

In actuality, an object's attributes are defines by its class.

Classes

Every object we've instantiated, or created, in Python has been of a class. A class is the definition of a kind of object. Technically, the data types we've become familiar with such as int or str are classes. And every integer or string we've used is an object of its respective class. This definition determines the aspects of the object such as those already listed. Furthermore, classes also define variables that hold data about the objects of that class. These variables or known as attributes.

Cat Class

Imagine I want to make objects that represent cats. And every cat will have attributes defining the characteristics of the cat. I can do this by creating a class.

class cat():
	pass

This code creates an empty class named cat. Recall that the pass keyword must be present if a structure is empty. Note that the parenthetical after the class name is optional.

class cat:
	pass

Not an object of a class can be created by calling that class name like we do functions. For example:

my_cat = cat()
stray_cat = cat()

This code assigns two variables to two different objects of the class cat.

Let's now add some attributes.

Attributes

An attribute is a variable defined within a class or object. Attributes can be assigned before or after an object is created. For example:

After Instantiation

my_cat.age = 7

This creates an age attribute and assigns that attribute to 7.

print(my_cat.age)

This code will print 7, which was assigned to the age attribute of my_cat.

Now say that a cat object's attribute is assigned to another cat object. For example:

my_cat.friend = stray_cat

This code assigns the variable my_cat's friend attribute to the other cat object stray_cat. But if we access my_cat.friend we will be returned the object itself. To access an attribute of that object we must double up the attribute names. For example if stray_cat has an attribute named color, it could be accessed with:

my_cat.friend.color

This code access my_cat's friend attribute, which is another cat object. The the color attribute of that other cat object is accessed.

Before Instantiation

Attributes can also be defined before an object of a class is ever created. This can be done within the class's body or definition. Note that this will initialize these attributes for every and any object created of this class. Here is an example cat class definition that defines an name, age, and color attribute.

class cat:
	def __init__(self, name, age, color):
		self.name = name
		self.age = age
		self.color = color

This code block defines the default attributes of a cat class. This class definition utilizes a special kind of function called a constructor. A constructor is a function that defines the default attributes of a class's objects. So when a an object of a class is created, it must have values for each default attribute. __init__() is the constructor in this case and also a kind of function called a double underscore or dunder function. These kinds of functions are discussed in the "...and more" section of the book because there are many more we have access to. For now, we will focus on __init.

__init() initializes the attributes of a class's objects and takes self as the first parameter. self is a variable that will point to the object being created. We can technically use another variable name, but self is the Python convention. Each parameter that follows, in this case name, age, and color, will be provided values for an object's attributes when it is created.

Let's now create an object of our new cat class.

my_cat = cat("Fluffy", "7", "Gray")

This code:

  • Looks up the definition of the cat class
  • Creates a new object
  • __init__ is called and provided the the object parameters
  • The attributes are stored in the object
  • my_cat is assigned to the object

Keep in mind these objects are like any object we've used thus far. They're just objects we've designed. And we can use them like we would any other object.

Methods

Like any other object the objects of or cat class can be used with dot functions or methods. Recall, that methods use the dot syntax and take an object as input. In actuality, methods are functions that are defined within a class for use on its objects. Let's define a method for our cat class that designates the cat object as a senior if it is above 10 years old.

def is_senior(self):
	if (self.age >= 10):
		return True
	else
		return False

This function named is_senior() returns True if the cat's age attribute is 10 or above and False if it is not. Note that for a class method, self must be the parameter, just like dunders, so the function can use the cat object that is created. Let's now nest this code within the class definition where it belongs.

class cat:
	def __init__(self, name, age, color):
		self.name = name
		self.age = age
		self.color = color
	def is_senior(self):
		if (self.age >= 10):
			return True
		else
			return False

Now, is_senior(my_cat) will return False, since my_cat.age is 7.


Further Reading

Python Docs On Classes

Classes In Computer Science

Inheritance

What if we want to create a new class based on a class that is already defined? We can do this through a concept called inheritance. Using inheritance is useful when we need a new class that's only slightly different than the one we have. With inheritance, we don't need to rewrite parts of the original class, which may break existing code. We also don't need to manually copy the definition from the class which may change in a future edit.

Creating a Child Class

Inheritance is the creation of a class based another class. The new class's definition will contain whatever the base class does plus new additions. The new class is said to inherit the aspects it shares from the base class. And continuing the analogy, the new class is said to be the child class, and the original base class is said to be the parent class.

Recall the cat class from the previous section below:

class cat:
    def __init__(self, name, age, color):
        self.name = name
        self.age = age
        self.color = color
    def is_senior(self):
        if (self.age >= 10):
            return True
        else
            return False

Now, let's create a child class of the cat class:

class sphynx(cat):
	pass

This is a definition of a child class named sphynx based on the cat class. Notice, to create a child class the class name of parent is given as a parameter of the child class. In this case the parent class is cat and is found in the parentheses as a parameter of sphynx. The child is class logically a kind of the parent class. It will have access to the same methods and have the same attributes as the parent.

sphynx The cat in question

hairless_cat = sphynx(smooth-skin, 3, pink)

Here, a sphynx object is created. It accepts all the same parameters as its parent because it currently has the same attributes. And it will have access to the same method is_senior.

hairless_cat.is_senior()

But what if I need the child to be different than its parent? For this, we need to utilize overriding.

Overriding

Overriding is the act of changing the definition of an attribute or method in a child class's definition. To override a method for example, we just rewrite the definition of that function in the child class's definition.

class sphynx(cat):
	def is_senior(self):
		if (self.age >= 10):
		print("I am a senior hairless cat")
            else
                return False

The is_senior() method has now been overridden. The method now prints a message in addition to returning True when the cat is of age.

__init()__, the constructor function which defines what data is accepted at object instantiation, may also be overridden. This is useful if the child objects need different default attributes. For example:

class sphynx(cat):
    def __init__(self, name, age, skin_color):
        self.name = name 
        self.age = age
        self.skin_color = color
    def is_senior(self):
	if (self.age >= 10):
	    print("I am a senior hairless cat")
        else
            return False

Here __init()__ is overridden by changing the last parameter, and corresponding attribute to skin_color... because sphynx cats are hairless and weird.

Keep in mind that the notion of inheritance can be extended as many times as needed. Thus child classes can have their own children, and those children may have children, and so forth.


Further Reading

Python Docs On Inheritance

Inheritance (object-oriented programming)

Magic Methods or Dunders

In Python there are built-in functions known as double underscore functions, or dunders for short; because their names begin and end in a double underscore. They are also sometimes referred to as magic methods. And while they may not be magical, because they're able to be understood, they are pretty cool.

We actually already have experience with a dunder: __init()__. Recall that this function is a constructor used to define a default class object. Essentially, a dunder is a function defined within a class that is not called directly, but by the class. Every class of every Python data type has dunders that define objects' attributes, and the meaning of operators' symbols such as + or * or ==.

The following are tables of dunders organized by the built-in class they are of:

Any Classes

Dunder MethodDescription
__init__Initializes a newly created instance of the class.
__str__Returns a string representation of the class instance.
__repr__Returns a string representation of the class instance for debugging.
__eq__Compares two class instances for equality using the == operator.
__ne__Compares two class instances for inequality using the != operator.

Integer

Dunder MethodDescription
__add__Performs addition with another integer using the + operator.
__sub__Performs subtraction with another integer using the - operator.
__mul__Performs multiplication with another integer using the * operator.
__divmod__Performs division with another integer and returns both quotient and remainder using the divmod() function.
__pow__Performs exponentiation with another integer using the ** operator.
__eq__Compares two integers for equality using the == operator.
__ne__Compares two integers for inequality using the != operator.
__lt__Compares two integers for less than using the < operator.
__gt__Compares two integers for greater than using the > operator.
__le__Compares two integers for less than or equal to using the <= operator.
__ge__Compares two integers for greater than or equal to using the >= operator.

String

Dunder MethodDescription
__len__Returns the length of the string.
__getitem__Allows indexing and slicing of the string.
__setitem__Raises an error as strings are immutable.
__delitem__Raises an error as strings are immutable.
__iter__Returns an iterator object for the string.
__contains__Checks if a substring is present in the string.
__add__Concatenates two strings using the + operator.
__mul__Replicates the string using the * operator.
__eq__Compares two strings for equality using the == operator.
__ne__Compares two strings for inequality using the != operator.
__lt__Compares two strings lexicographically using the < operator.
__gt__Compares two strings lexicographically using the > operator.
__le__Compares two strings lexicographically using the <= operator.
__ge__Compares two strings lexicographically using the >= operator.

List

Dunder MethodDescription
__len__Returns the number of items in the list.
__getitem__Allows indexing and slicing of the list.
__setitem__Allows assignment to specific indices of the list.
__delitem__Allows deletion of specific indices from the list.
__iter__Returns an iterator object for the list.
__contains__Checks if an item is present in the list.
__add__Allows concatenation of two lists using the + operator.
__mul__Allows replication of the list using the * operator.
__eq__Compares two lists for equality using the == operator.
__ne__Compares two lists for inequality using the != operator.
__lt__Compares two lists for less than using the < operator.
__gt__Compares two lists for greater than using the > operator.
__le__Compares two lists for less than or equal to using the <= operator.
__ge__Compares two lists for greater than or equal to using the >= operator.

Overloading

Like how class attributes and methods can be overridden, dunders can be overloaded. Overloading is replacing the default behavior of an operator symbol or function with your own. In Python operators can be overloaded. And this makes sense if you recall that the same operator sometimes has different behavior depending on the type. For instance, the + operator adds integers and floats, but concatenates strings. This is because the string class is overloading the + operator in its definition. This can be accomplished using our cat class. Recall its definition below:

class cat:
    def __init__(self, name, age, color):
        self.name = name
        self.age = age
        self.color = color
    def is_senior(self):
        if (self.age >= 10):
			return True
        else
            return False

Now let's redefine the __add__() dunder in our cat class to create a new cat object when two cat objects are "added" together:

class cat:
    def __init__(self, name, age, color):
        self.name = name
        self.age = age
        self.color = color
    def is_senior(self):
        if (self.age >= 10):
            return True
        else
            return False
    def __add__(self, other):
        return cat(new_cat, 0, red)

In this code the __add__() dunder is overloaded. The parameters self and other will point to two cat objects, and the function now returns a cat with age 0 when the cat objects are "added" with +.


Further Reading

Operator Overloading

Pip

Pip is a Python package manager. It is optionally installed alongside Python.

Package Managers

A package manager is a program that handles installing, updating, and organizing software. Instead of going out to the internet to search for software, a package manager can be used as a one stop shop. It is conceptually similar to the app stores that we are all familiar with on our smartphones. And there are many package managers for the many different programming languages and operating systems. In our case pip package manager is written in Python, and is designed to install Python programs. Many Python programs written by individuals and groups are available through pip.

Recall that in Python packages are simply collections of modules or other subpackages. Therfore, pip is also used to install Python modules locally for use in our own Python programs.

Using pip

Pip is a command line program. pip -h or pip --help will display all options and subcommands.

Installing Packages

Packages can be installed using the install subcommand.

pip install packageName

Uninstalling packages

Packages can be uninstalled using the uninstall subcommand.

pip uninstall packageName

Listing installed packages

A list of all installed packages can be displayed with the list subcommand.

pip list

Further Reading

Pip Man Pages

Pip Documentation

Python Package Repository Search

Escape Sequence

Escape sequences or escape characters in programming are characters that have a meaning beyond the character itself. These character are usually used to represent whitespace such as tabs, spaces, escape, or newlines as in Enter. Escape characters can also drop a characters special meaning within the confines of a programming language for its use as a literal character, like within a string for example. Escape characters are usually denoted by a backslash: \.

Common Escape Sequences are:

Escape SequenceMeaning
\nNewline
\tTab
\bBackspace
\rCarriage Return (Return to beginning of line)
\aAudible Bell (Produces a beep sound)
'Escape Single Quote
"Escape Double Quote
\Escape Backslash

Examples

Newline character (\n)

Printing on separate lines:

print("Hello\nWorld")

Output:

Hello

World

Tab character (\t)

Creating a tabular format:

print("Name\tAge")
print("John\t25")
print("Alice\t30")

Output:

Name Age

John 25

Alice 30

Backslash character (/)

Escaping special characters:

print("This is a backslash: \\")

Output:

This is a backslash:

Single quote (') and double quote (")

Embedding quotes in strings:

print("He said, \"Hello!\"")
print('I\'m fine.')

Output:

He said, "Hello!"

I'm fine.

Carriage return (\r)

Overwriting a line:

print("Loading...", end='\r')
# Perform some time-consuming task here
print("Done!")

Unicode character (\uXXXX and \UXXXXXXXX)

Using Unicode characters:

print("\u2665")  # Heart symbol (U+2665)
print("\U0001F600")  # Grinning face emoji (U+1F600)

Output:

😄

Unicode and Ascii will be discussed in the following section.


Further Reading

Escape Characters

Escape Sequences

ASCII and Unicode

ASCII

ASCII or (American Standard Code for Information Interchange) is a character encoding standard. In other words, it is a rule set used to determine what bit patterns represent what characters in the English language and other keys such as Tab and Return. ASCII was developed from telegraph codes such as Morse code, and is conceptually similar.

Here is an ASCII table for reference: ASCII

The ASCII standard utilizes 8 bits which is a single byte. This allows for 127 possible patters than can be used to represent different characters and keystrokes.

But what if we need more? Only having access to Latin characters doesn't make this standard international. What if we want to represent characters of languages that don't use Latin characters such a Greek, Japanese, or Arabic? Furthermore, what if we want to represent other kinds of characters like images such as glyphs or emojis? For this we need another standard called Unicode.

Unicode

Unicode or The Unicode Standard is a encoding standard that is a superset of ASCII. That means that Unicode includes ASCII encoding among other standards. The goal of Unicode is to unify the world's languages and methods of text encoding into a single universal standard.

Unicode supports methods of encoding that utilize up to 32 bits. That is 4 bytes. And 4,294,967,296 possible characters.

There are far too many Unicode characters to list but know that essentially every world language and script is supported, along with every glyph and emoji we use every day.

Emojis In Python

Websites such as Unicode Lookup are databases that can be searched for a specific character or emoji. The value that encodes the character can be used in scripts and will be printed as the emoji. For example:

message = "I love " + "\U0001F499" + " Python"  # Heart emoji
print(message)

Outputs:

I love 💙 Python

Try looking up some emojis for yourself and see what you can do with them in Python.


Further Reading

ASCII

Unicode Org

Command Line Arguments

Many programming languages, including Python, support the use of command line arguments. They are also sometimes referred to as switches. A command line argument is essentially a way of configuring and applying settings when a program or script is ran at the command line.

Refer to the first chapter's section Command Line Interface or CLI for more information.

In Python, command line arguments are best implemented through the module argparse available in the standard library. This module helps with:

  • Defining Arguments
  • Storing Arguments
  • Designating default values
  • Designating required arguments
  • Designing help messages

For examples that utilize command line arguments, check the examples and projects sections.


Further Reading

argparse

Version Control

Searching and Sorting Algorithms

A common field of computer science is the study and development of algorithms. Remember algorithms are just methods of solving a problem. Algorithms can be developed, however as a programmer, algorithms are often memorized or noted. This is so they can be used as a tool whenever they might be useful. One of the most critical categories of algorithms are those for sorting and searching collections of data. In Python, any collection type, like lists, can be sorted or searched.

Algorithm Efficiency

Algorithms are generally determined to be efficient in terms of how quickly they complete their task. This is known as time complexity. Furthermore, how efficient an algorithms is can also be determined in terms of how much memory is used to complete the task. This is known as space complexity. These are more advanced concepts that won't be delved into here. Just keep in mind some algorithms are more fast and efficient than others, depending on the set of data they are working on.

Sorting Algorithms

Bubble Sort

Bubble Sort is one of the simplest sorting algorithms. The algorithm works by repeatedly swapping the adjacent elements if they are in the wrong order. It continues to pass through the list until it is completely sorted, which is when no more swaps are needed.

def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        # Last i elements are already in place
        for j in range(0, n - i - 1):
            # Swap if the element found is greater than the next element
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]

Selection Sort

Selection Sort is another simple sorting algorithm. It works by dividing the input list into two parts: the sublist of items already sorted and the sublist of items remaining to be sorted. The algorithm repeatedly selects the smallest (or largest, depending on sorting order) element from the unsorted sublist, swapping it with the leftmost unsorted element, and moving the sublist boundaries one element to the right.

def selection_sort(arr):
    for i in range(len(arr)):
        # Find the minimum element in remaining unsorted array
        min_idx = i
        for j in range(i + 1, len(arr)):
            if arr[min_idx] > arr[j]:
                min_idx = j
                
        # Swap the found minimum element with the first element of the unsorted part        
        arr[i], arr[min_idx] = arr[min_idx], arr[i]

Insertion Sort

Insertion sort works similarly to how you might sort playing cards in your hand. The array is divided into a sorted and an unsorted region. One by one, the unsorted values are "inserted" into their correct position in the sorted region.

def insertion_sort(arr):
   for i in range(1, len(arr)):
       key = arr[i]
       # Move elements of arr[0..i-1], that are greater than key,
       # to one position ahead of their current position
       j = i - 1
       while j >= 0 and key < arr[j]:
           arr[j + 1] = arr[j]
           j -= 1
       arr[j + 1] = key

Quick Sort

Quick Sort is a divide-and-conquer algorithm. It picks an element as a pivot and partitions the given array around the pivot. There are different versions of quickSort that pick pivot in different ways: always pick the first element, always pick the last element, pick a random element, pick the median, etc. Once the array is partitioned, the two sub-arrays are recursively sorted.

def partition(arr, low, high):
    i = (low - 1)         # index of smaller element
    pivot = arr[high]     # pivot
  
    for j in range(low, high):
        # If current element is smaller than or equal to pivot
        if arr[j] <= pivot:
            # increment index of smaller element
            i = i + 1
            arr[i], arr[j] = arr[j], arr[i]
  
    arr[i + 1], arr[high] = arr[high], arr[i + 1]
    return (i + 1)
  
def quick_sort(arr, low, high):
    if len(arr) == 1:
        return arr
    if low < high:
        # pi is partitioning index, arr[p] is now at right place
        pi = partition(arr, low, high)
  
        # Separately sort elements before partition and after partition
        quick_sort(arr, low, pi - 1)
        quick_sort(arr, pi + 1, high)

Merge Sort

Merge Sort is also a divide-and-conquer algorithm. It works by dividing the array into two halves, sorting them individually, and then merging them. This process is recursive, with the base case being lists of size 1, which are already sorted. The merge operation is the key process that assumes that the two lists are sorted and merges them into a single sorted list.

def merge_sort(arr):
    if len(arr) <= 1:
        return arr

    mid = len(arr) // 2
    left_half = arr[:mid]
    right_half = arr[mid:]

    return merge(merge_sort(left_half), merge_sort(right_half))

def merge(left, right):
    merged = []
    left_index = 0
    right_index = 0

    # Merge smaller elements first
    while left_index < len(left) and right_index < len(right):
        if left[left_index] < right[right_index]:
            merged.append(left[left_index])
            left_index += 1
        else:
            merged.append(right[right_index])
            right_index += 1

    # If there are remaining elements in left or right half, append them to the result
    while left_index < len(left):
        merged.append(left[left_index])
        left_index += 1

    while right_index < len(right):
        merged.append(right[right_index])
        right_index += 1

    return merged

Searching Algorithms

Linear Search is the simplest searching algorithm. It works by sequentially checking each element of the list until a match is found or the whole list has been searched.

def linear_search(arr, x):
    for i in range(len(arr)):
        if arr[i] == x:
            return i  # return the index of found element
    return -1  # if the element is not found

Binary Search is a much faster search algorithm than linear search. It works on the principle of divide and conquer. For this algorithm to work properly, the data collection should be in the sorted form. Binary search looks for a particular item by comparing the middle most item of the collection. If a match occurs, then the index of the item is returned. If the middle item is greater than the item, then the item is searched in the sub-array to the left of the middle item. Otherwise, the item is searched for in the sub-array to the right of the middle item. This process continues on the sub-array as well until the size of the subarray reduces to zero.

def binary_search(arr, low, high, x):
    if high >= low:
        mid = (high + low) // 2
        # If element is present at the middle
        if arr[mid] == x:
            return mid
        # If element is smaller than mid, then it can only be present in left subarray
        elif arr[mid] > x:
            return binary_search(arr, low, mid - 1, x)
        # Else the element can only be present in right subarray
        else:
            return binary_search(arr, mid + 1, high, x)
    else:
        # Element is not present in array
        return -1

Further Reading and Watching

15 Sorting Algorithms in 6 Minutes

Sorting Algorithms

Search Algorithms

Being Well-Rounded

TermDescription
AlgorithmThe definition of a process or instructions to be carried to to complete a task.
Arithmetic OperationAn operation that accepts and returns numerical values.
AssignmentGiving a name to an object by which the object can be referenced.
BinaryCode or number system containing only 0s and 1s; What a computer fundamentally understands.
BitAn entity with only two possible states represented by 0 and 1.
BodyThe code block following a conditional or function declaration.
BooleanA data type that has only two possible values: true or false.
Built-InA function or data type defined by the authors of a programming language.
By ReferenceTo provide an object itself to a function.
By ValueTo provide only the value of an object to a function
CallingTo execute a function. *Call;Called
CastingConverting one data type to another. *Cast; Casted
ClassDefines attributes of an object.
CollectionsTypes that contain multiple elements such as lists and strings.
CommandA word that executes a program.
Command Line Interface (cli)A textual method of interacting with a computer system opposed to a graphical environment.
CommentA line of code that is skipped by the interpreter. For human readability.
Comparison OperationAn operation that performs a test and accepts numerical values and returns truth values.
CompilerA program that converts source code of a compiled language to a binary file. *Compiler;Compilation
Conditional statementA statement which evaluates the truth value of a case.
ConstructorA method that defines the default object of a class. Similar to a template.
DataInformation. Usually ultimately stored in the form of binary data.
Data TypeA data organization that defines the meaning of the data.
DeclarativeProgramming paradigm where the state of the system is defined or declared. Such as a markup or templating language.
DefinitionThe code that determines the actions of a function.
Double Underscore Method (Dunder)A method whose name begins and ends in double underscores. Is called by the class.
elseA keyword beginning a conditional else statement.
Escape Character or Escape SequenceCharacters meaning something other than its literal value.
Executable FileA binary file that can be ran as a program on a computer often ending in .exe.
FunctionCode that is encapsulated. May accept inputs or return outputs.
ifA keyword beginning a conditional if statement.
ImperativeParadigm where instructions are given to a system for execution.
importKeyword that brings into scope other source code.
importPython keyword that denotes a module to be included.
IndexThe numbered "container" which "holds" an element in a collection.
InheritanceThe mechanism that allows classes to be derived from one another similar to a familial hierarchy.
InstantiationThe creation of an object; the bringing of an object into existence.
Integrated Development EnvironmentA program used to edit source code
InterpreterA program that executed the source code of an interpreted language. *Interpreted;Interpretation
IterationThe execution of a body of a loop relative to other executions in a series. *iterate; iterating
KeywordA word in a programming language that is protected for a certain used and not allowed for use as a variable name.
Logical OperationAn operation that accepts and returns truth values.
loopA code block that executes until a condition is not met.
MethodA function of a class to accept an object of said class as input. *Dot Function
ModuleSource code that can be imported for use; also known as a library.
ModuleSource code that can be reference and used by other source code.
NestingContaining code blocks such as functions or conditionals within one another.
ObjectA concept defining an entity of a some data type and its existence. Data type; location; times used; etc.
Object Oriented Programming (OOP)Programming paradigm where data is organized by attributes.
OperatorA symbol denoting an operation on one or between multiple objects or entities.
OptionA setting usable at the command line. *Switch
OverloadThe act of redefining an operation through the use of dunders in a class definition.
OverrideThe act of redefining a method in a child class's definition.
ParadigmForms of a programming language that indicate how it is written in and how the source is executed by the system.
ParameterThe input of a function.
PathA location within a file system.
pipA Python package manager.
PointerA kind of variable which refers or points to an object. Variables in Python are pointers by default. *Reference
PortabilityThe aspect of a language that defines how easily its programs can be ran on a wide variety of systems.
PrecedenceThe order of operations in a programming language. Higher precedence is executed before lower precedence.
PromptA symbol or group of systems denoting the current line in a command line interface.
RecursionThe act of a code block calling itself.
ScopeData other code is aware of. *Scoping
ShellA program that offers an environment in which to interact with the system. Usually referring to a shell on the command line.
ShorthandThe combination of multiple operators or processes and their functionalities into a single operator or symbol.
Source CodeThe expression of a programming language as a text file before compilation or interpretation.
StatementCode that expresses an action to be carried out.
StyleThe ways a language can express meaning based on the preferences of the author.
SyntaxThe rules dictating how a language expresses meaning.
TerminalA program that displays a command line interface. *Terminal Emulator
Text EditorA program used to edit source code.
Truth TableA table expressing the inputs and outputs of logical operations.
VariableA name used to label data.
Zero Based IndexingParadigm where the index numbering of collections begin at zero.

Command Line Interface Guide

Common Commands

This is a table of useful some commands for use at the command line found on most operating systems. These commands are for general use, and allow for the navigation of the system, and operation of the system. Note that commands used to delete data must be used responsibly.

CommandFunction
lsList contents of a directory. Uses current directory by default.
mvMove to a given directory
cpCopy a given file to a given destination, can effectively rename files
rmdirDeletes an empty directory
rmDeletes a file
pwdLists current path
whoamiDisplays user's name
clearClears terminal

Command Hotkeys and Shortcuts

At the command line certain keys and key combinations can be used to perform actions that make using a computer at the command line more convenient and more efficient. Many are ctrl plus another key, or the arrow keys. Some useful hotkeys are listed in the table below.

HotkeyFunction
UpCycle through history
ctrl+cKill current command or line
ctrl+lClear terminal
ctril+wDelete current word
ctrl+/ctrl-Increase or decrease font size

Dunders

Class

Dunder MethodDescription
__init__Initializes a newly created instance of the class.
__str__Returns a string representation of the class instance.
__repr__Returns a string representation of the class instance for debugging.
__eq__Compares two class instances for equality using the == operator.
__ne__Compares two class instances for inequality using the != operator.

Function

Dunder MethodDescription
__call__Allows the function to be called as if it were a regular function.
__repr__Returns a string representation of the function.
__doc__Returns the docstring associated with the function.

Iterator

Dunder MethodDescription
__iter__Returns the iterator object itself.
__next__Retrieves the next item from the iterator.

Context Manager

Dunder MethodDescription
__enter__Returns the context manager itself or an object related to the context.
__exit__Defines the behavior when exiting the context manager.

Generator

Dunder MethodDescription
__iter__Returns the generator object itself.
__next__Retrieves the next generated value from the generator.

List

Dunder MethodDescription
__len__Returns the number of items in the list.
__getitem__Allows indexing and slicing of the list.
__setitem__Allows assignment to specific indices of the list.
__delitem__Allows deletion of specific indices from the list.
__iter__Returns an iterator object for the list.
__contains__Checks if an item is present in the list.
__add__Allows concatenation of two lists using the + operator.
__mul__Allows replication of the list using the * operator.
__eq__Compares two lists for equality using the == operator.
__ne__Compares two lists for inequality using the != operator.
__lt__Compares two lists for less than using the < operator.
__gt__Compares two lists for greater than using the > operator.
__le__Compares two lists for less than or equal to using the <= operator.
__ge__Compares two lists for greater than or equal to using the >= operator.

String

Dunder MethodDescription
__len__Returns the length of the string.
__getitem__Allows indexing and slicing of the string.
__setitem__Raises an error as strings are immutable.
__delitem__Raises an error as strings are immutable.
__iter__Returns an iterator object for the string.
__contains__Checks if a substring is present in the string.
__add__Concatenates two strings using the + operator.
__mul__Replicates the string using the * operator.
__eq__Compares two strings for equality using the == operator.
__ne__Compares two strings for inequality using the != operator.
__lt__Compares two strings lexicographically using the < operator.
__gt__Compares two strings lexicographically using the > operator.
__le__Compares two strings lexicographically using the <= operator.
__ge__Compares two strings lexicographically using the >= operator.

Tuple

Dunder MethodDescription
__len__Returns the number of items in the tuple.
__getitem__Allows indexing and slicing of the tuple.
__setitem__Raises an error as tuples are immutable.
__delitem__Raises an error as tuples are immutable.
__iter__Returns an iterator object for the tuple.
__contains__Checks if an item is present in the tuple.
__add__Concatenates two tuples using the + operator.
__mul__Replicates the tuple using the * operator.
__eq__Compares two tuples for equality using the == operator.
__ne__Compares two tuples for inequality using the != operator.
__lt__Compares two tuples lexicographically using the < operator.
__gt__Compares two tuples lexicographically using the > operator.
__le__Compares two tuples lexicographically

using the <= operator. __ge__ | Compares two tuples lexicographically using the >= operator.

Dictionary

Dunder MethodDescription
__len__Returns the number of key-value pairs in the dictionary.
__getitem__Allows accessing a value by key using indexing.
__setitem__Allows assigning a value to a key in the dictionary.
__delitem__Allows deleting a key-value pair from the dictionary.
__iter__Returns an iterator object for the dictionary keys.
__contains__Checks if a key is present in the dictionary.
__eq__Compares two dictionaries for equality using the == operator.
__ne__Compares two dictionaries for inequality using the != operator.

Set

Dunder MethodDescription
__len__Returns the number of elements in the set.
__contains__Checks if an element is present in the set.
__iter__Returns an iterator object for the set.
__eq__Compares two sets for equality using the == operator.
__ne__Compares two sets for inequality using the != operator.
__lt__Checks if the set is a proper subset of another set using the < operator.
__gt__Checks if the set is a proper superset of another set using the > operator.
__le__Checks if the set is a subset of another set using the <= operator.
__ge__Checks if the set is a superset of another set using the >= operator.

File

Dunder MethodDescription
__enter__Returns a context manager for the file.
__exit__Defines the behavior when exiting the context manager.
__iter__Returns an iterator object for reading lines from the file.

Integer

Dunder MethodDescription
__add__Performs addition with another integer using the + operator.
__sub__Performs subtraction with another integer using the - operator.
__mul__Performs multiplication with another integer using the * operator.
__divmod__Performs division with another integer and returns both quotient and remainder using the divmod() function.
__pow__Performs exponentiation with another integer using the ** operator.
__eq__Compares two integers for equality using the == operator.
__ne__Compares two integers for inequality using the != operator.
__lt__Compares two integers for less than using the < operator.
__gt__Compares two integers for greater than using the > operator.
__le__Compares two integers for less than or equal to using the <= operator.
__ge__Compares two integers for greater than or equal to using the >= operator.

Decimal

Dunder MethodDescription
__add__Performs addition with another decimal using the + operator.
__sub__Performs subtraction with another decimal using the - operator.
__mul__Performs multiplication with another decimal using the * operator.
__truediv__Performs division with another decimal using the / operator.
__floordiv__Performs floor division with another decimal using the // operator.
__mod__Performs modulus (remainder) operation with another decimal using the % operator.
__pow__Performs exponentiation with another decimal using the ** operator.
__eq__Compares two decimals for equality using the == operator.
__ne__Compares two decimals for inequality using the != operator.
__lt__Compares two decimals for less than using the < operator.
__gt__Compares two decimals for greater than using the > operator.
__le__Compares two decimals for less than or equal to using the <= operator.
__ge__Compares two decimals for greater than or equal to using the >= operator.

Date

Dunder MethodDescription
__str__Returns a string representation of the date.
__repr__Returns a string representation of the date for debugging.
__eq__Compares two dates for equality using the == operator.
__ne__Compares two dates for inequality using the != operator.
__lt__Compares two dates for less than using the < operator.
__gt__Compares two dates for greater than using the > operator.
__le__Compares two dates for less than or equal to using the <= operator.
__ge__Compares two dates for greater than or equal to using the >= operator.

Time

Dunder MethodDescription
__str__Returns a string representation of the time.
__repr__Returns a string representation of the time for debugging.
__eq__Compares two times for equality using the == operator.
__ne__Compares two times for inequality using the != operator.
__lt__Compares two times for less than using the < operator.
__gt__Compares two times for greater than using the > operator.
__le__Compares two times for less than or equal to using the <= operator.
__ge__Compares two times for greater than or equal to using the >= operator.

Datetime

Dunder MethodDescription
__str__Returns a string representation of the datetime.
__repr__Returns a string representation of the datetime for debugging.
__eq__Compares two datetimes for equality using the == operator.
__ne__Compares two datetimes for inequality using the != operator.
__lt__Compares two datetimes for less than using the < operator.
__gt__Compares two datetimes for greater than using the > operator.
__le__Compares two datetimes for less than or equal to using the <= operator.
__ge__Compares two dat

Regular Expression

Dunder MethodDescription
__init__Initializes a regular expression pattern.
__repr__Returns a string representation of the regular expression pattern.
__str__Returns a string representation of the regular expression pattern.
__eq__Compares two regular expression patterns for equality using the == operator.
__ne__Compares two regular expression patterns for inequality using the != operator.
__match__Matches the regular expression pattern against a string from the start.
__search__Searches for the regular expression pattern in a string.
__findall__Finds all occurrences of the regular expression pattern in a string.
__finditer__Returns an iterator yielding match objects for all occurrences of the regular expression pattern in a string.

Enum

Dunder MethodDescription
__str__Returns a string representation of the enum member.
__repr__Returns a string representation of the enum member for debugging.
__eq__Compares two enum members for equality using the == operator.
__ne__Compares two enum members for inequality using the != operator.
__lt__Compares two enum members for less than using the < operator.
__gt__Compares two enum members for greater than using the > operator.
__le__Compares two enum members for less than or equal to using the <= operator.
__ge__Compares two enum members for greater than or equal to using the >= operator.

Bytes

Dunder MethodDescription
__len__Returns the number of bytes in the bytes object.
__getitem__Allows indexing of the bytes object.
__setitem__Allows assignment to specific indices of the bytes object.
__iter__Returns an iterator object for the bytes object.
__contains__Checks if a byte value is present in the bytes object.
__add__Concatenates two bytes objects using the + operator.
__mul__Replicates the bytes object using the * operator.
__eq__Compares two bytes objects for equality using the == operator.
__ne__Compares two bytes objects for inequality using the != operator.
__lt__Compares two bytes objects lexicographically using the < operator.
__gt__Compares two bytes objects lexicographically using the > operator.
__le__Compares two bytes objects lexicographically using the <= operator.
__ge__Compares two bytes objects lexicographically using the >= operator.

Range

Dunder MethodDescription
__len__Returns the number of items in the range.
__getitem__Allows indexing of the range.
__iter__Returns an iterator object for the range.
__contains__Checks if a value is present in the range.
__eq__Compares two ranges for equality using the == operator.
__ne__Compares two ranges for inequality using the != operator.

Complex

Dunder MethodDescription
__abs__Returns the absolute value (magnitude) of the complex number.
__add__Performs addition with another complex number using the + operator.
__sub__Performs subtraction with another complex number using the - operator.
__mul__Performs multiplication with another complex number using the * operator.
__truediv__Performs division with another complex number using the / operator.
__eq__Compares two complex numbers for equality using the == operator.
__ne__Compares two complex numbers for inequality using the != operator.
__str__Returns a string representation of the complex number.
__repr__Returns a string representation of the complex number for debugging.

bytearray

Dunder MethodDescription
__len__Returns the number of elements in the bytearray.
__getitem__Allows indexing of the bytearray.
__setitem__Allows assignment to specific indices of the bytearray.
__iter__Returns an iterator object for the bytearray.
__contains__Checks if a value is present in the bytearray.
__add__Concatenates two bytearrays using the + operator.
__mul__Replicates the bytearray using the * operator.
__eq__Compares two bytearrays for equality using the == operator.
__ne__Compares two bytearrays for inequality using the != operator.
__lt__Compares two bytearrays lexicographically using the < operator.
__gt__Compares two bytearrays lexicographically using the > operator.
__le__Compares two bytearrays lexicographically using the <= operator.
__ge__Compares two bytearrays lexicographically using the >= operator.

memoryview

Dunder MethodDescription
__len__Returns the number of elements in the memoryview.
__getitem__Allows indexing of the memoryview.
__setitem__Allows assignment to specific indices of the memoryview.
__iter__Returns an iterator object for the memoryview.
__contains__Checks if a value is present in the memoryview.
__eq__Compares two memoryviews for equality using the == operator.
__ne__Compares two memoryviews for inequality using the != operator.
__str__Returns a string representation of the memoryview.
__repr__Returns a string representation of the memoryview for debugging.

frozenset

Dunder MethodDescription
__len__Returns the number of elements in the frozenset.
__contains__Checks if an element is present in the frozenset.
__iter__Returns an iterator object for the frozenset.
__eq__Compares two frozensets for equality using the == operator.
__ne__Compares two frozensets for inequality using the != operator.
__lt__Checks if the frozenset is a proper subset of another frozenset using the < operator.
__gt__Checks if the frozenset is a proper superset of another frozenset using the > operator.
__le__

| Checks if the frozenset is a subset of another frozenset using the <= operator. __ge__ | Checks if the frozenset is a superset of another frozenset using the >= operator.

Set

Dunder MethodDescription
__len__Returns the number of elements in the set.
__contains__Checks if an element is present in the set.
__iter__Returns an iterator object for the set.
__eq__Compares two sets for equality using the == operator.
__ne__Compares two sets for inequality using the != operator.
__lt__Checks if the set is a proper subset of another set using the < operator.
__gt__Checks if the set is a proper superset of another set using the > operator.
__le__Checks if the set is a subset of another set using the <= operator.
__ge__Checks if the set is a superset of another set using the >= operator.
__add__Performs set union with another set using the + operator.
__sub__Performs set difference with another set using the - operator.
__and__Performs set intersection with another set using the & operator.
__or__Performs set union with another set using the `
__xor__Performs set symmetric difference with another set using the ^ operator.

FrozenSet

Dunder MethodDescription
__len__Returns the number of elements in the frozenset.
__contains__Checks if an element is present in the frozenset.
__iter__Returns an iterator object for the frozenset.
__eq__Compares two frozensets for equality using the == operator.
__ne__Compares two frozensets for inequality using the != operator.
__lt__Checks if the frozenset is a proper subset of another frozenset using the < operator.
__gt__Checks if the frozenset is a proper superset of another frozenset using the > operator.
__le__Checks if the frozenset is a subset of another frozenset using the <= operator.
__ge__Checks if the frozenset is a superset of another frozenset using the >= operator.

Dict

Dunder MethodDescription
__len__Returns the number of key-value pairs in the dictionary.
__getitem__Allows indexing of the dictionary using keys.
__setitem__Allows assignment of values to keys in the dictionary.
__delitem__Allows deletion of keys and their corresponding values from the dictionary.
__contains__Checks if a key is present in the dictionary.
__iter__Returns an iterator object for the keys of the dictionary.
__eq__Compares two dictionaries for equality using the == operator.
__ne__Compares two dictionaries for inequality using the != operator.
__str__Returns a string representation of the dictionary.
__repr__Returns a string representation of the dictionary for debugging.

DefaultDict

Dunder MethodDescription
__len__Returns the number of key-value pairs in the defaultdict.
__getitem__Allows indexing of the defaultdict using keys.
__setitem__Allows assignment of values to keys in the defaultdict.
__delitem__Allows deletion of keys

Practice Questions

This is a list of practice assignments. These assignments can be completed using the knowledge from this book, Python standard modules, and built in functions. These assignments are organized by difficulty level.

Easy

Calculator

Write a program that asks the user for two numbers and an operator (+, -, *, /). The program should perform the corresponding calculation and display the result.

Even or Odd

Write a program that asks the user for a number and determines whether it is even or odd.

Leap Year Checker

Write a program that asks the user for a year and determines whether it is a leap year or not.

Positive Numbers In a List

Write a program that takes a list of numbers as input and prints only the positive numbers.

Reverse a String

Write a program that asks the user for a string and prints the reverse of that string.

Mad Libs

Write a program that asks the user for various words (e.g., noun, adjective, verb) and then generates a story by replacing placeholders in a template with the user's input.

Hangman

Write a program that plays the Hangman game. The program should choose a random word from a list, and the user has to guess letters until they guess the whole word or run out of attempts.

Number Guessing Game

Write a program that generates a random number between 1 and 100 and asks the user to guess it. The program should provide hints (higher/lower) after each incorrect guess and keep track of the number of attempts.

Random Password Generator

Write a program that generates a random password for the user. The program should ask the user for the desired length of the password and include a combination of uppercase letters, lowercase letters, numbers, and special characters.

Intermediate

Palindrome Checker

Write a program that asks the user for a word and determines whether it is a palindrome (reads the same forwards and backwards).

Prime Numbers in Range

Write a program that asks the user for a range of numbers and prints all the prime numbers within that range.

Word Count

Write a program that reads a text file and counts the occurrences of each word. The program should display the word count for each unique word.

Difficult

Fibonacci Sequence

Write a program that generates the Fibonacci sequence up to a specified number of terms. The program should ask the user for the number of terms and display the sequence.

Recommended Software

Text Editors

Notepad++

Geany

Integrated Development Environments (IDEs)

PyCharm Community Edition

Eclipse

Apps

Android

Pydroid

IOS

Pyto

Terminal Emulators

Windows Terminal

Kitty

Alacritty

Interpreters

Official Python Interpreter

PyPy

Online Interpreters

Programiz Online Interpreter & Compiler

References and Resources

References

Lubanovic, B. (2019). Introducing Python: Modern Computing in Simple Packages. “O’Reilly Media, Inc.”

Introducing Python: Modern Computing in Simple Packages


Matthes, E. (2015). Python Crash Course: A Hands-On, Project-Based Introduction to Programming.

Python Crash Course: A Hands-On, Project-Based Introduction to Programming


Official Python Documentation

Official Python Documentation


Reitz, K.,& Schlusser, T. (2016). The hitchhiker’s guide to python: Best practices for development. O’Reilly Media, Inc.

The Hitchhiker's Guide To Python


Rosetta Code


Harvard CS50’s Introduction to Programming with Python – Full University Course: Taught By Dr. David J. Malan


Output and User Input

# This script demonstrates how to print a simple message in Python

# Use the `print` function to display a message
print("Hello, world!")

# You can print multiple values by separating them with commas
print("The sum of 2 and 3 is:", 2 + 3)

# You can also print variables
name = "Alice"
age = 25
print("My name is", name, "and I am", age, "years old.")
# This script demonstrates how to get user input in Python

# Use the `input` function to prompt the user for input
name = input("Enter your name: ")

# The `input` function returns a string, which can be stored in a variable
print("Hello,", name + "!")

# You can convert the input to a specific data type using type casting
age = int(input("Enter your age: "))
print("You are", age, "years old.")

# You can also prompt the user for multiple values
x = float(input("Enter a number: "))
y = float(input("Enter another number: "))
print("The sum of", x, "and", y, "is:", x + y)
# This script demonstrates the use of escape sequences in Python strings

# Use the escape character (\) to include special characters in a string
print("This is a double-quote (\")")

# The newline escape sequence (\n) creates a new line
print("First line\nSecond line")

# The tab escape sequence (\t) inserts a tab
print("Name:\tJohn")

# The backslash escape sequence (\\) prints a backslash
print("Path: C:\\Programs\\Python")

# You can combine multiple escape sequences in a single string
print("Here's a backslash (\\), a double-quote (\") and a new line (\n)")

# The raw string prefix (r) ignores escape sequences
print(r"This is a raw string\n")

Data Types

Ints

# This script demonstrates the integer data type in Python

# Integers are whole numbers without a fractional component
age = 25
print("My age is:", age)

# Integers can be positive or negative
temperature = -10
print("The temperature is:", temperature)

# Integers support mathematical operations
x = 10
y = 5
sum = x + y
print("The sum of", x, "and", y, "is:", sum)

Floats

# This script demonstrates the float data type in Python

# Floats are numbers with a decimal point
pi = 3.14
print("The value of pi is:", pi)

# Floats can be positive or negative
temperature = -10.5
print("The temperature is:", temperature)

# Floats support mathematical operations
radius = 2.5
area = 3.14 * radius**2
print("The area of the circle is:", area)

Strings

# This script demonstrates the string data type in Python

# Strings are sequences of characters enclosed in quotes
name = "Alice"
print("My name is:", name)

# Strings can contain letters, numbers, and symbols
message = "Hello, 123!"
print("Message:", message)

# Strings can be concatenated using the plus (+) operator
greeting = "Hello"
subject = "world"
full_greeting = greeting + ", " + subject + "!"
print("Full greeting:", full_greeting)

Booleans

# This script demonstrates the boolean data type in Python

# Booleans represent truth values: True or False
is_student = True
print("Is the person a student?", is_student)

# Booleans are often used in conditional statements
x = 5
y = 10
is_greater = x > y
print("Is x greater than y?", is_greater)

# Booleans can be combined using logical operators (and, or, not)
a = True
b = False
result1 = a and b
result2 = a or b
result3 = not b
print("Result 1:", result1)
print("Result 2:", result2)
print("Result 3:", result3)

Lists

# This script demonstrates the list data type in Python

# Lists are ordered collections of items enclosed in square brackets
fruits = ['apple', 'banana', 'orange', 'kiwi']
print("Fruits:", fruits)

# Lists can contain different data types: strings, numbers, booleans, etc.
mixed_list = ['apple', 123, True, 3.14]
print("Mixed list:", mixed_list)

# Accessing list elements using index (starts from 0)
first_fruit = fruits[0]
print("First fruit:", first_fruit)

# Modifying list elements
fruits[1] = 'grape'
print("Updated fruits:", fruits)

# Lists can have nested lists (a list within a list)
nested_list = [['a', 'b', 'c'], [1, 2, 3], ['x', 'y', 'z']]
print("Nested list:", nested_list)

# List length using the len() function
num_fruits = len(fruits)
print("Number of fruits:", num_fruits)

# Adding elements to a list using the append() method
fruits.append('mango')
print("Updated fruits (after appending):", fruits)

# Removing elements from a list using the remove() method
fruits.remove('orange')
print("Updated fruits (after removing):", fruits)

# Slicing lists to extract sublists
subset = fruits[1:3]
print("Subset:", subset)

# Checking if an element exists in a list using the 'in' operator
is_apple_present = 'apple' in fruits
print("Is 'apple' present in fruits?", is_apple_present)

Variables

Assignment

# This script demonstrates variables in Python

# Variables are used to store and manipulate data
name = "Alice"  # Assigning a string value to the variable 'name'
age = 25  # Assigning an integer value to the variable 'age'
is_student = True  # Assigning a boolean value to the variable 'is_student'

# You can print the values stored in variables
print("Name:", name)
print("Age:", age)
print("Is Student?", is_student)

# Variables can be updated with new values
age = age + 1  # Incrementing the value of 'age' by 1
is_student = False  # Updating the value of 'is_student'

print("Updated Age:", age)
print("Updated Is Student?", is_student)

# Variables can store different data types
x = 5  # An integer variable
y = 3.14  # A float variable
message = "Hello"  # A string variable

print("x:", x)
print("y:", y)
print("Message:", message)

# Variables can be used in calculations or string concatenation
result = x + y  # Adding 'x' and 'y' and storing the result in 'result'
greeting = message + ", " + name  # Concatenating 'message', a comma, and 'name'

print("Result:", result)
print("Greeting:", greeting)

Variables As References

# This script demonstrates variables as references to objects in Python

# Variables are references to objects
x = 5
y = x  # 'y' now references the same object as 'x'

# Modifying the object referenced by 'x'
x = 10

# The value of 'y' remains unchanged, as it references a different object
print("x:", x)  # Output: 10
print("y:", y)  # Output: 5

# Lists as mutable objects
fruits = ['apple', 'banana', 'orange']
basket = fruits  # 'basket' references the same object as 'fruits'

# Modifying the object referenced by 'fruits'
fruits.append('kiwi')

# The object referenced by 'basket' is also modified
print("fruits:", fruits)  # Output: ['apple', 'banana', 'orange', 'kiwi']
print("basket:", basket)  # Output: ['apple', 'banana', 'orange', 'kiwi']

# Immutable objects and reassignment
name1 = "Alice"
name2 = name1  # 'name2' references the same object as 'name1'

# Reassigning 'name1' to a new object
name1 = "Bob"

# The object referenced by 'name2' remains unchanged
print("name1:", name1)  # Output: "Bob"
print("name2:", name2)  # Output: "Alice"

Arithmwtic Operations

Arithmetic Operations

# This script demonstrates addition in Python

# Addition of integers
a = 5
b = 3
result1 = a + b
print("Addition of", a, "and", b, "is:", result1)

# Addition of floats
x = 2.5
y = 1.75
result2 = x + y
print("Addition of", x, "and", y, "is:", result2)

# Addition of integers and floats
p = 10
q = 2.5
result3 = p + q
print("Addition of", p, "and", q, "is:", result3)

# Addition of strings (concatenation)
message1 = "Hello"
message2 = " world!"
result4 = message1 + message2
print("Concatenation of strings:", result4)
# This script demonstrates subtraction in Python

# Subtraction of integers
a = 10
b = 4
result1 = a - b
print("Subtraction of", a, "and", b, "is:", result1)

# Subtraction of floats
x = 3.5
y = 1.25
result2 = x - y
print("Subtraction of", x, "and", y, "is:", result2)
# This script demonstrates multiplication in Python

# Multiplication of integers
a = 3
b = 5
result1 = a * b
print("Multiplication of", a, "and", b, "is:", result1)

# Multiplication of floats
x = 2.5
y = 1.5
result2 = x * y
print("Multiplication of", x, "and", y, "is:", result2)
# This script demonstrates division in Python

# Division of integers
a = 10
b = 3
result1 = a / b
print("Division of", a, "and", b, "is:", result1)

# Division of floats
x = 5.5
y = 2.0
result2 = x / y
print("Division of", x, "and", y, "is:", result2)
# This script demonstrates the modulo operation in Python

# Modulo of integers
a = 10
b = 3
result1 = a % b
print("Modulo of", a, "and", b, "is:", result1)

# Modulo of floats
x = 5.5
y = 2.0
result2 = x % y
print("Modulo of", x, "and", y, "is:", result2)

Shorthand

# Shorthand addition (+=)
x = 5
x += 3  # Equivalent to x = x + 3
print("x:", x)  # Output: 8

# Shorthand addition with strings
message = "Hello"
message += " world!"  # Equivalent to message = message + " world!"
print("Message:", message)  # Output: "Hello world!"
# Shorthand subtraction (-=)
x = 10
x -= 4  # Equivalent to x = x - 4
print("x:", x)  # Output: 6
# Shorthand multiplication (*=)
x = 3
x *= 5  # Equivalent to x = x * 5
print("x:", x)  # Output: 15
# Shorthand division (/=)
x = 10
x /= 2  # Equivalent to x = x / 2
print("x:", x)  # Output: 5.0
# Shorthand modulo (%=)
x = 10
x %= 3  # Equivalent to x = x % 3
print("x:", x)  # Output: 1
# Shorthand exponentiation (**=)
x = 2
x **= 3  # Equivalent to x = x ** 3
print("x:", x)  # Output: 8

Logical Operations

# This script demonstrates the logical AND operation in Python

# Logical AND of booleans
a = True
b = False
result1 = a and b
print("Logical AND of", a, "and", b, "is:", result1)

# Logical AND with expressions
x = 10
y = 5
result2 = (x > 5) and (y < 10)
print("Logical AND of", (x > 5), "and", (y < 10), "is:", result2)
# This script demonstrates the logical OR operation in Python

# Logical OR of booleans
a = True
b = False
result1 = a or b
print("Logical OR of", a, "and", b, "is:", result1)

# Logical OR with expressions
x = 10
y = 5
result2 = (x > 5) or (y > 10)
print("Logical OR of", (x > 5), "and", (y > 10), "is:", result2)
# This script demonstrates the logical NOT operation in Python

# Logical NOT of booleans
a = True
result1 = not a
print("Logical NOT of", a, "is:", result1)

# Logical NOT with expressions
x = 10
result2 = not (x > 5)
print("Logical NOT of", (x > 5), "is:", result2)

Precedence

Precedence of Arithmetic Operators

# This script demonstrates operator precedence for arithmetic operators in Python

# Example 1: Multiplication and addition
result = 2 + 3 * 4
print("Result:", result)  # Output: 14

# Example 2: Parentheses to override precedence
result = (2 + 3) * 4
print("Result:", result)  # Output: 20

Precedence of Comparison Operators

# This script demonstrates operator precedence for comparison operators in Python

# Example 1: Greater than and equality
result = 5 > 3 == True
print("Result:", result)  # Output: False

# Example 2: Parentheses to override precedence
result = 5 > (3 == True)
print("Result:", result)  # Output: True

Precedence of Logical Operators

# This script demonstrates operator precedence for logical operators in Python

# Example 1: Logical AND and OR
result = True or False and False
print("Result:", result)  # Output: True

# Example 2: Parentheses to override precedence
result = (True or False) and False
print("Result:", result)  # Output: False

Precedence of Mixed Operators

# This script demonstrates operator precedence with mixed operators in Python

# Example 1: Arithmetic, comparison, and logical operators
result = (10 + 5) * 2 > 20 and 3 != 4
print("Result:", result)  # Output: True

# Example 2: Parentheses to override precedence
result = (10 + 5) * (2 > 20) and (3 != 4)
print("Result:", result)  # Output: False

Type Conversion

Explicit Type Conversion (Type Casting)

# This script demonstrates explicit type conversion (type casting) in Python

# Integer to String
x = 10
x_str = str(x)  # Explicitly convert 'x' to a string
print("x_str:", x_str, "Type:", type(x_str))

# Float to Integer
y = 3.14
y_int = int(y)  # Explicitly convert 'y' to an integer
print("y_int:", y_int, "Type:", type(y_int))

# String to Integer
num_str = "25"
num_int = int(num_str)  # Explicitly convert 'num_str' to an integer
print("num_int:", num_int, "Type:", type(num_int))

Implicit Type Conversion (Automatic Type Conversion)

# This script demonstrates implicit type conversion (automatic type conversion) in Python

# Integer to Float
x = 10
y = 2.5
result = x + y  # Implicitly convert 'x' to a float before addition
print("result:", result, "Type:", type(result))

# Float to String
a = 3.14
message = "The value of pi is " + str(a)  # Implicitly convert 'a' to a string for concatenation
print("message:", message, "Type:", type(message))

# Integer to Boolean
b = 0
is_valid = bool(b)  # Implicitly convert 'b' to a boolean
print("is_valid:", is_valid, "Type:", type(is_valid))

Dot Functions

Dot Function For Strings

# This script demonstrates dot functions for strings in Python

# Example 1: String length
message = "Hello, world!"
length = len(message)
print("Length of the string:", length)

# Example 2: Uppercase and lowercase conversions
name = "John Doe"
uppercase_name = name.upper()
lowercase_name = name.lower()
print("Uppercase name:", uppercase_name)
print("Lowercase name:", lowercase_name)

# Example 3: String concatenation
greeting = "Hello"
name = "Alice"
message = greeting + ", " + name + "!"
print("Greeting message:", message)

# Example 4: Checking if a string starts or ends with a specific substring
text = "Python programming is fun!"
starts_with_python = text.startswith("Python")
ends_with_fun = text.endswith("fun!")
print("Starts with 'Python':", starts_with_python)
print("Ends with 'fun!':", ends_with_fun)

Dot Functions For Lists

# This script demonstrates dot functions for lists in Python

# Example 1: Adding elements to a list
numbers = [1, 2, 3]
numbers.append(4)
print("Updated list:", numbers)

# Example 2: Removing elements from a list
fruits = ['apple', 'banana', 'orange']
fruits.remove('banana')
print("Updated list:", fruits)

# Example 3: Sorting a list
scores = [80, 95, 70, 85]
scores.sort()
print("Sorted list:", scores)

# Example 4: Reversing a list
names = ['Alice', 'Bob', 'Charlie']
names.reverse()
print("Reversed list:", names)

Dot Functions For Numbers

# This script demonstrates dot functions for numbers in Python

# Example 1: Absolute value
number = -5
absolute_value = abs(number)
print("Absolute value:", absolute_value)

# Example 2: Rounding
pi = 3.14159
rounded_value = round(pi, 2)
print("Rounded value:", rounded_value)

# Example 3: Exponentiation
base = 2
exponent = 3
result = pow(base, exponent)
print("Exponentiation result:", result)

Conditional Statements

if

# This script demonstrates the usage of the if statement in Python

# Example 1: Single if statement
x = 10

if x > 5:
    print("x is greater than 5")

# Example 2: if-else statement
y = 3

if y % 2 == 0:
    print("y is even")
else:
    print("y is odd")

Nested Conditionals

# This script demonstrates the usage of nested if statements in Python

# Example 1: Nested if statements
x = 5
y = 3

if x > 0:
    if y > 0:
        print("x and y are positive")
    else:
        print("x is positive, but y is not")
else:
    print("x is not positive")

elif

# This script demonstrates the usage of the elif statement in Python

# Example 1: Multiple elif statements
grade = 75

if grade >= 90:
    print("Grade: A")
elif grade >= 80:
    print("Grade: B")
elif grade >= 70:
    print("Grade: C")
elif grade >= 60:
    print("Grade: D")
else:
    print("Grade: F")

Multiple Conditions

# This script demonstrates multiple conditions in Python

# Example 1: Multiple conditions
x = 5

if x > 0 and x % 2 == 0:
    print("x is a positive even number")
elif x > 0 and x % 2 != 0:
    print("x is a positive odd number")
else:
    print("x is either negative or zero")

Loops

While

# This script demonstrates a simple while loop in Python

# Example 1: Simple while loop
count = 1

while count <= 5:
    print("Count:", count)
    count += 1
# This script demonstrates an infinite loop with a break statement in Python

# Example 1: Infinite loop with break statement
while True:
    name = input("Enter your name: ")
    
    if name == "quit":
        break
    
    print("Hello,", name)
# This script demonstrates loop control with a continue statement in Python

# Example 1: Loop control with continue statement
count = 0

while count < 5:
    count += 1
    
    if count == 3:
        continue
    
    print("Count:", count)

For

# This script demonstrates iterating over a list using a for loop in Python

# Example 1: Iterating over a list
fruits = ["apple", "banana", "cherry", "date"]

for fruit in fruits:
    print(fruit)
# This script demonstrates iterating over a range using a for loop in Python

# Example 1: Iterating over a range
for i in range(1, 6):
    print("Count:", i)
# This script demonstrates iterating over a string using a for loop in Python

# Example 1: Iterating over a string
message = "Hello, World!"

for char in message:
    if char == " ":
        continue
    
    print(char)

User Defined Functions

Simple Function

# This script demonstrates the definition and usage of a simple user-defined function in Python

# Example 1: Simple function
def greet():
    print("Hello, world!")

# Call the function
greet()

Function with Parameters

# This script demonstrates a user-defined function with parameters in Python

# Example 1: Function with parameters
def greet(name):
    print("Hello,", name)

# Call the function with an argument
greet("Alice")

Function with Return Value

# This script demonstrates a user-defined function with a return value in Python

# Example 1: Function with return value
def add_numbers(a, b):
    return a + b

# Call the function and store the result
result = add_numbers(5, 3)

# Print the result
print("Sum:", result)

Classes

Simple Class

# This script demonstrates the definition and usage of a simple class in Python

# Example 1: Simple class
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height

# Create an instance of the Rectangle class
rect = Rectangle(5, 3)

# Call the area() method
print("Area:", rect.area())

Class Method

# This script demonstrates a class method in Python

# Example 1: Class method
class MathUtils:
    @classmethod
    def add(cls, a, b):
        return a + b

# Call the class method
result = MathUtils.add(5, 3)
print("Sum:", result)

Class Inheritance

# This script demonstrates class inheritance in Python

# Example 1: Class inheritance
class Animal:
    def __init__(self, name):
        self.name = name
    
    def sound(self):
        pass

class Dog(Animal):
    def sound(self):
        return "Woof!"

class Cat(Animal):
    def sound(self):
        return "Meow!"

# Create instances of the derived classes
dog = Dog("Buddy")
cat = Cat("Whiskers")

# Call the sound() method on each instance
print(dog.name, "makes", dog.sound())
print(cat.name, "makes", cat.sound())

Import

Importing a Module

# This script demonstrates importing a module in Python

# Example 1: Importing a module
import math

# Using functions from the math module
radius = 5
area = math.pi * math.pow(radius, 2)
print("Area of the circle:", area)

Importing Specific Functions

# This script demonstrates importing specific functions from a module in Python

# Example 1: Importing specific functions
from random import randint, choice

# Using imported functions
random_number = randint(1, 10)
fruit = choice(["apple", "banana", "cherry", "date"])
print("Random number:", random_number)
print("Random fruit:", fruit)

Importing a Module with an Alias

# This script demonstrates importing a module with an alias in Python

# Example 1: Importing a module with an alias
import datetime as dt

# Using the module with the alias
current_time = dt.datetime.now()
print("Current time:", current_time)

Style

# This script demonstrates Python coding style conventions

# Variable names should be descriptive and follow lowercase_with_underscores
first_name = "Alice"
last_name = "Smith"

# Constants should be in uppercase_with_underscores
MAX_VALUE = 100
PI = 3.14159

# Indentation should be 4 spaces (not tabs) per level
if True:
    print("This is indented correctly")

# Use meaningful whitespace and blank lines for readability
def add_numbers(a, b):
    result = a + b
    
    return result


# Use spaces around operators and after commas
x = 5
y = 10
z = x + y

my_list = [1, 2, 3, 4, 5]

# Use docstrings to provide documentation for functions and modules
def multiply(a, b):
    """
    Multiply two numbers and return the result.
    
    Args:
        a: The first number.
        b: The second number.
        
    Returns:
        The product of a and b.
    """
    result = a * b
    return result


# Follow PEP 8 guidelines for import statements and module-level code
import math


# Use meaningful variable and function names, and write self-explanatory code
def calculate_circle_area(radius):
    """
    Calculate the area of a circle.
    
    Args:
        radius: The radius of the circle.
        
    Returns:
        The area of the circle.
    """
    area = math.pi * radius ** 2
    return area


# Write concise and expressive code, avoiding unnecessary complexity
def is_even(num):
    return num % 2 == 0


# Comment code to explain intent and clarify complex parts
def process_data(data):
    # Check if data is valid
    if data:
        # Process the data
        processed_data = perform_complex_operations(data)
        return processed_data
    else:
        # Invalid data, return None
        return None


# Use proper spacing and alignment for better readability
def calculate_average(numbers):
    total = sum(numbers)
    count = len(numbers)
    average = total / count
    
    return average

FizzBuzz

FizzBuzz is a well known game that is often given to programmers during interviews to test whether or not they are familiar with basic programming concepts such as conditional statements and loops. This game is notable because while simple it can be solved in multiple ways, some more optimal and clever than others.

The rules of the game are this:

  • Count up from 1 to 100. However,
  • If the number is a factor of 3 (i.e divisible by 3), say Fizz
  • If the number is a factor of 5 (i.e divisible by 5), say Buzz
  • If the number is a factor of both (i.e divisible by both), say FizzBuzz

Attempt this problem on your own before viewing these solution. Remember, its testing basic skills such as the use of conditional statements and loops.

The Basic Solution

# Loops through range of numbers 1-100
for i in range(1, 101):
# If current number is factor of both print FizzBuzz
	if i % 3 == 0 and i % 5 == 0:
		print("FizzBuzz")
# Factor of 3 print Fizz
	elif i % 3 == 0:
		print("Fizz")
# Factor of 5 print Buzz
	elif i % 5 == 0:
		print("Buzz")
# Otherwise, print the number itself
	else:
		print(i)

Now notice that mathematically a number that is a factor of both 3 and 5, is a factor of 15. Therefor, the first condition can be just a check for 15.

or i in range(1, 101):
    if i % 15 == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        print(i)

Notice that these solution duplicate much of the code. It would probably be most computationally efficient and cleanest to avoid repeating the same conditional checks. The next set of solutions accomplish this.

No Duplication Solution

for i in range(1, 101):
# Initializes an empty string to output
	output = ""
# Appends Fizz to empty string if 3 is a factor
	if i % 3 == 0:
		output += "Fizz"
# Appends Buzz to empty string if 5 is a factor
	if i % 5 == 0:
		output += "Buzz"
# If string remainds empty, as in neither 3 nor 5 were factors,
# assign output to number itself
	if output == "":
		output = i
	print(output)

Here is an even more succinct solution which cleverly utilizes the not and or operators.

for n in range(1,101):
    response = ''
# Output of conditions are inverted by not
# So, if n % 3 == 0, it will be inverted to 1, which represents True, so the body will execute.
    if not n%3:
        response += 'Fizz'
    if not n%5:
        response += 'Buzz'
# Here if response is empty the number itself is printed. 
    print(response or n)

Here is a further explanation of the last line print(response or n):

The logical OR operator in Python evaluates the expression from left to right and returns the first operand that evaluates to True. If none of the operands evaluate to True, it returns the last operand. In this context, an empty string evaluates to a Boolean False or 0.

These FizzBuzz examples demonstrate that the simplest of problems can have a wide variety of solution, and that you the reader, currently have what it takes to write real programs to test and advance your abilities.


Further Reading and Watching

FizzBuzz: One Simple Interview Question

Many FizzBuzz Solutions in Many Languages

The Collatz Conjecture

A mathematical conjecture is a statement or rule that is proposed, and likely true, but still unproven or disproven. A famous unsolved problem is mathematics is the Collatz Conjecture. It was first proposed by Lothar Collatz in 1937.

The conjecture is as follows:

For any positive integer, if it is even divide it by 2. If it is odd multiply it by 3 and add 1. Continue indefinitely. Eventually 1 will be reached. In fact, for every tested number an infinite cycle of 4, 2, 1 is reached.

The conjecture can be demonstrated in a program through a basic use of loops.

Basic Example

def collatz (num):
    for iteration in range(1,100):
# If even, n / 2
        if num % 2 == 0:
            num /= 2
        else:
# If odd, 3n + 1
            num = (3 * num) + 1 
        print(num)

# Only accepts a positive integer
while (True): 
    num = int(input("Please enter a positive integer...\n"))
    if num > 0:
        break
    
collatz(num)

In addition to generating a sequence of Collatz numbers, it gets the number to begin the sequence from the user. Furthermore, a while loop is utilized to ensure the number is a positive integer. If you run this script, no matter the number you will always reach the 4,2,1 cycle. Keep in mind, the end of the range represents the number of iterations. Some numbers take more iterations to reach this cycle than others. so this range may need to be made larger depending on the number.

This project demonstrates that the ability to demonstrate some of the most unsolvable problems in math and science is now at your fingertips.


Further Reading and Watching

The Simplest Math Problem No One Can Solve - Collatz Conjecture

UNCRACKABLE? The Collatz Conjecture - Numberphile

Collatz conjecture

Random Password Generator

In the modern world it has become more and more important to consider one's security and safety online. One aspect of this is maintaining complex and unique passwords. Often those who wish to have truly random and unique passwords will use random password generators. These generators often utilize cryptographic and information concepts to generate passwords that are unlikely to be guess through brute force. A central concept is Entropy, which is a measurement of the number of guesses required to exhaust all possibilities.

No randomly generated number is truly random; it is psuedorandom. While psuedorandmoness may appear truly random to a human, there is always some algorithm or process by which a random value is selected by a generator. The amount of randomness is mostly determined by the seed provided to the generator. A seed is a value that a generator accepts which initializes the generator's algorithm. And if the seed and generator used is known by an attacker, the attacker can produce the same password. So the seed must be as random as possible. The Python standard module random provides random number generation, however it is not random enough to use for passwords. The secrets standard module is much more appropriate. This modules obtains seeds form the operating system which are much more random than default seeds used in by modules. Operating systems generate randomness using very ephemeral and constantly changing values such as memory states, mouse movements, keyboard inputs, and circuit timings.

A Random Password Generator

This generator utilizes two modules. The secrets module offers a random password generator suited for security, and argparse which offers a command line argument parser. The command line arguments defined in the following script allow the user to set the password length, and turn off the generation of special characters, and access a help message.

import argparse
import secrets

parser = argparse.ArgumentParser(
                    prog='Secure Password Generator',
                    description='Generates a random password',
                    epilog='Stay Secure!')
parser.add_argument('-l', '--length', default=21, dest="length", help='Choose password length. (Default length is 21)' )
parser.add_argument('-n', '--nospecial', action='store_true', required=False, dest="nospecial", help='turn off generation of special characters')

password = ""
args = parser.parse_args()

if(args.nospecial):
	chars = list(range(48,57)) + list(range(65,60)) + list(range(97,122))
else:
	chars = list(range(33,126))

for char in range(1,int(args.length) + 1):
	password += chr(secrets.choice(chars))

print('''
.----------------.  .----------------.  .----------------.  .----------------.   .----------------.  .----------------.  .----------------.  .----------------.  .----------------.  .----------------. 
| .--------------. || .--------------. || .--------------. || .--------------. | | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. |
| |    _______   | || |  _________   | || |      __      | || |  ____  ____  | | | |    _______   | || |  _________   | || |     ______   | || | _____  _____ | || |  _______     | || |  _________   | |
| |   /  ___  |  | || | |  _   _  |  | || |     /  \     | || | |_  _||_  _| | | | |   /  ___  |  | || | |_   ___  |  | || |   .' ___  |  | || ||_   _||_   _|| || | |_   __ \    | || | |_   ___  |  | |
| |  |  (__ \_|  | || | |_/ | | \_|  | || |    / /\ \    | || |   \ \  / /   | | | |  |  (__ \_|  | || |   | |_  \_|  | || |  / .'   \_|  | || |  | |    | |  | || |   | |__) |   | || |   | |_  \_|  | |
| |   '.___`-.   | || |     | |      | || |   / ____ \   | || |    \ \/ /    | | | |   '.___`-.   | || |   |  _|  _   | || |  | |         | || |  | '    ' |  | || |   |  __ /    | || |   |  _|  _   | |
| |  |`\____) |  | || |    _| |_     | || | _/ /    \ \_ | || |    _|  |_    | | | |  |`\____) |  | || |  _| |___/ |  | || |  \ `.___.'\  | || |   \ `--' /   | || |  _| |  \ \_  | || |  _| |___/ |  | |
| |  |_______.'  | || |   |_____|    | || ||____|  |____|| || |   |______|   | | | |  |_______.'  | || | |_________|  | || |   `._____.'  | || |    `.__.'    | || | |____| |___| | || | |_________|  | |
| |              | || |              | || |              | || |              | | | |              | || |              | || |              | || |              | || |              | || |              | |
| '--------------' || '--------------' || '--------------' || '--------------' | | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' |
 '----------------'  '----------------'  '----------------'  '----------------'   '----------------'  '----------------'  '----------------'  '----------------'  '----------------'  '----------------' 
''')
print("YOUR PASSWORD\n-------------------\n"+password+"\n-------------------\nKEEP THIS PASSWORD SAFE!")

Further Reading

Password Strength

Random Seed

Entropy