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
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.
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.
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
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.
https://www.python.org/downloads/
Once the installer is downloaded, go to the directory it was downloaded to and execute it.
The Python installer I downloaded to my computer.
Once the installer is launched you will be greeted by this screen:
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.
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 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
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:
Name | Type | Description | Mutable | Examples |
---|---|---|---|---|
Integer | int | Any integer | No | 7,10,24,-24,-8564, 103811 |
Floating Point Number | float | Any decimal number | No | -73.38, 89.92, 1.0001 |
Complex | complex | Any complex number | No | 11+7j, -4j |
Boolean | bool | A truth value | No | True, False |
String | str | A sequence of characters such as a word or sentence | No | "Steve", "Jenny", "I saw a balloon." |
List | list | A list or array of the same data objects | Yes | ["Me,"You","Not Them"] |
Tuple | tuple | A list or array of objects of any differing types | No | ("Me","You",1,2,4.8) |
Dictionary | dict | A list of key-pair values | No | "Me":"Yes", "You":"Yes", "Them":"No" |
Set | set | A list of key values | yes | set([3,5,7]) |
Frozen Set | frozenset | An immutable set | no | frozenset[("me","you) |
Bytes | bytes | A byte value | no | b'ab\xff' |
ByteArray | bytearray | A list or array of byte values | Yes | bytearray(...) |
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
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.
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:
- a is pointed to an integer object with a value of 7.
- b is pointed to the value that a point to (7).
- a is pointed to a new integer object with a value if 11.
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
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:
Operator | Description | Example | Result Returned |
---|---|---|---|
+ | Addition | 7+7 | 14 |
- | Subtraction | 70-1 | 69 |
* | Multiplication | 7*7 | 49 |
/ | Floating-point division | 7 / 2 | 3.5 |
// | Integer or Truncated Division | 7 // 2 | 3 |
% | Modulus or Remainder of Integer Division | 7 % 3 | 1 |
** | Exponentiation | 7 ** 2 | 49 |
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
Operator | Description |
---|---|
= | 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
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 1 | Input 2 | Output |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
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 1 | Input 2 | Output |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
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 1 | Output |
---|---|
0 | 1 |
1 | 0 |
A NOT truth table
Further Reading
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.
Operation | Name |
---|---|
() | 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 |
not | Boolean NOT |
and | Boolean AND |
or | Boolean 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
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
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:
Name | Operator | Description | Example |
---|---|---|---|
Equality | == | Check if operands are equal | 2 == 2 |
Inequality | != | Check if operands are not equal | 4 != 2 |
Less Than | < | Check if left operand is less than right operand | 2 < 4 |
Less Than or Equal | <= | Check if left operand is less than or equal to right operand | 6 <= 7 |
Greater Than | > | Check if left operand is greater than right operand | 8 > 4 |
Greater Than or Equal | >= | Check if left operand is greater than or equla to right operand | 7 >= 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.
- A condition is checked
- If the condition is true, the body executes. The body is the code block that will execute if condition is true.
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
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.
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.
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
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.
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
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. 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:
- Assigns n to the integer 0.
- Begins a loop that will execute until n is 10.
- Prints n.
- Increments n by 1.
- 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
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.
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.
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.
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
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:
Module | Description |
---|---|
math | Provides mathematical functions |
cmath | Provides mathematical functions for use with complex numbers |
datetime | Provides clocks and counters |
random | Provides generation of random numbers and values |
os | Provides tools for interaction with the operating system |
io | Provides 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
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
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.
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
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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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
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
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 Sequence | Meaning |
---|---|
\n | Newline |
\t | Tab |
\b | Backspace |
\r | Carriage Return (Return to beginning of line) |
\a | Audible 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
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:
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
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
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
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
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
Being Well-Rounded
Term | Description |
---|---|
Algorithm | The definition of a process or instructions to be carried to to complete a task. |
Arithmetic Operation | An operation that accepts and returns numerical values. |
Assignment | Giving a name to an object by which the object can be referenced. |
Binary | Code or number system containing only 0s and 1s; What a computer fundamentally understands. |
Bit | An entity with only two possible states represented by 0 and 1. |
Body | The code block following a conditional or function declaration. |
Boolean | A data type that has only two possible values: true or false. |
Built-In | A function or data type defined by the authors of a programming language. |
By Reference | To provide an object itself to a function. |
By Value | To provide only the value of an object to a function |
Calling | To execute a function. *Call;Called |
Casting | Converting one data type to another. *Cast; Casted |
Class | Defines attributes of an object. |
Collections | Types that contain multiple elements such as lists and strings. |
Command | A word that executes a program. |
Command Line Interface (cli) | A textual method of interacting with a computer system opposed to a graphical environment. |
Comment | A line of code that is skipped by the interpreter. For human readability. |
Comparison Operation | An operation that performs a test and accepts numerical values and returns truth values. |
Compiler | A program that converts source code of a compiled language to a binary file. *Compiler;Compilation |
Conditional statement | A statement which evaluates the truth value of a case. |
Constructor | A method that defines the default object of a class. Similar to a template. |
Data | Information. Usually ultimately stored in the form of binary data. |
Data Type | A data organization that defines the meaning of the data. |
Declarative | Programming paradigm where the state of the system is defined or declared. Such as a markup or templating language. |
Definition | The 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. |
else | A keyword beginning a conditional else statement. |
Escape Character or Escape Sequence | Characters meaning something other than its literal value. |
Executable File | A binary file that can be ran as a program on a computer often ending in .exe. |
Function | Code that is encapsulated. May accept inputs or return outputs. |
if | A keyword beginning a conditional if statement. |
Imperative | Paradigm where instructions are given to a system for execution. |
import | Keyword that brings into scope other source code. |
import | Python keyword that denotes a module to be included. |
Index | The numbered "container" which "holds" an element in a collection. |
Inheritance | The mechanism that allows classes to be derived from one another similar to a familial hierarchy. |
Instantiation | The creation of an object; the bringing of an object into existence. |
Integrated Development Environment | A program used to edit source code |
Interpreter | A program that executed the source code of an interpreted language. *Interpreted;Interpretation |
Iteration | The execution of a body of a loop relative to other executions in a series. *iterate; iterating |
Keyword | A word in a programming language that is protected for a certain used and not allowed for use as a variable name. |
Logical Operation | An operation that accepts and returns truth values. |
loop | A code block that executes until a condition is not met. |
Method | A function of a class to accept an object of said class as input. *Dot Function |
Module | Source code that can be imported for use; also known as a library. |
Module | Source code that can be reference and used by other source code. |
Nesting | Containing code blocks such as functions or conditionals within one another. |
Object | A 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. |
Operator | A symbol denoting an operation on one or between multiple objects or entities. |
Option | A setting usable at the command line. *Switch |
Overload | The act of redefining an operation through the use of dunders in a class definition. |
Override | The act of redefining a method in a child class's definition. |
Paradigm | Forms of a programming language that indicate how it is written in and how the source is executed by the system. |
Parameter | The input of a function. |
Path | A location within a file system. |
pip | A Python package manager. |
Pointer | A kind of variable which refers or points to an object. Variables in Python are pointers by default. *Reference |
Portability | The aspect of a language that defines how easily its programs can be ran on a wide variety of systems. |
Precedence | The order of operations in a programming language. Higher precedence is executed before lower precedence. |
Prompt | A symbol or group of systems denoting the current line in a command line interface. |
Recursion | The act of a code block calling itself. |
Scope | Data other code is aware of. *Scoping |
Shell | A program that offers an environment in which to interact with the system. Usually referring to a shell on the command line. |
Shorthand | The combination of multiple operators or processes and their functionalities into a single operator or symbol. |
Source Code | The expression of a programming language as a text file before compilation or interpretation. |
Statement | Code that expresses an action to be carried out. |
Style | The ways a language can express meaning based on the preferences of the author. |
Syntax | The rules dictating how a language expresses meaning. |
Terminal | A program that displays a command line interface. *Terminal Emulator |
Text Editor | A program used to edit source code. |
Truth Table | A table expressing the inputs and outputs of logical operations. |
Variable | A name used to label data. |
Zero Based Indexing | Paradigm 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.
Command | Function |
---|---|
ls | List contents of a directory. Uses current directory by default. |
mv | Move to a given directory |
cp | Copy a given file to a given destination, can effectively rename files |
rmdir | Deletes an empty directory |
rm | Deletes a file |
pwd | Lists current path |
whoami | Displays user's name |
clear | Clears 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.
Hotkey | Function |
---|---|
Up | Cycle through history |
ctrl+c | Kill current command or line |
ctrl+l | Clear terminal |
ctril+w | Delete current word |
ctrl+/ctrl- | Increase or decrease font size |
Dunders
Class
Dunder Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__iter__ | Returns the iterator object itself. |
__next__ | Retrieves the next item from the iterator. |
Context Manager
Dunder Method | Description |
---|---|
__enter__ | Returns the context manager itself or an object related to the context. |
__exit__ | Defines the behavior when exiting the context manager. |
Generator
Dunder Method | Description |
---|---|
__iter__ | Returns the generator object itself. |
__next__ | Retrieves the next generated value from the generator. |
List
Dunder Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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 Method | Description |
---|---|
__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
Integrated Development Environments (IDEs)
Apps
Android
IOS
Terminal Emulators
Interpreters
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
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
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
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!")