Python Beginner Guide

Introduction

This guide is for complete beginners who wish to learn how to use Python.   The examples are specific to the Windows operating system (OS), but much of the training content is applicable to the use of Python with other operating systems.  

Why Another Python Beginner Tutorial

Despite how user friendly and powerful the Python programming language is, getting started using Python correctly can be a serious challenge.   I have been programming my entire life, using languages such as BASIC, Pascal, C#, C++, JavaScript, Fortran, PHP, MATLAB, VBA, VBScript, and many more, but getting started in Python was strangely the most challenging.   This guide is targeted at getting a beginner over the pain points quickly and easily.

Why Python?

From my perspective, the Python language is a well structured and easy to learn.   It is supported by so many libraries, it is rare that you would need to create your own library in order to accomplish a task.   If it runs too slow for your application, you can speed it up.   If you need to deploy it as a complied application, or as a web application, no problem.   Work with Big Data, data science projects, time series data, AI, and with Python you have access to cutting edge solutions.  

Index


Windows Command Prompt

You will occasionally need to use the Windows Command Prompt when working with Python, installing libraries, and working with virtual environments.  

The Command Prompt is a command line interpreter application available in most Windows operating systems.   Command Prompt is also called Windows Command Processor, command shell, cmd prompt, and even its filename cmd.exe.   Note that Windows has two command-line shells: the Command Prompt, and PowerShell.   Think of the Command Prompt as the CLI (command line interface) for the Windows OS.  

You can find the Command Prompt by browsing the Windows start menu for the application named 'Command Prompt', or searching for the application 'Command Prompt'.   When you open the Command Prompt application, it will have a title of 'Command Prompt' at the top of the application window.   If it says "Windows PowerShell", exit that application and continue to find 'Command Prompt'.   You can exit the 'Command Prompt' application by either clicking the 'x' in the upper right corner of the application window, or entering the command 'exit' followed by the return key.

Open the Command Prompt.   Within the Command Prompt window (click inside the window), type in the command 'py --list-paths' followed by the return key.


py --list-paths

If Python is installed, one or more versions will be displayed, such as what is shown below.   If Python is not found (installed), no problem.  

Useful Command Prompt Commands

In order to create and user Virtual Environments, it is necessary to use the Command Prompt to:

  • View folders in the current folder (dir *.)
  • Change the current folder (chdir)
  • Create a subfolder in the current folder (mkdir)
  • Remove/delete a subfolder (rmdir)

 

NOTE: In all cases except for the 'dir' command, the Windows Command Prompt commands listed above are the same as those for Linux.   Each of the commands have an alias: cd / chdir, md / mkdir, rm / rmdir.   Linux uses the 'ls' command to see a folder's contents.

Below is a complete example of viewing folders, creating a folder, changing the current folder to the created folder, changing the current folder to the parent of the current folder, and removing the folder.   From the Windows Command Prompt, try the following:


dir *.
mkdir junk
chdir junk
dir 
chdir ..
dir *.
rmdir junk
dir *.

You can use the Windows File Explorer in parallel to the actions above to confirm the actions taken.   If you have any trouble with the Command Prompt commands, do independent research and study until you are comfortable with them.  

Installing Python

Checking What Python Versions Are Installed

For many reasons, you may already have one or more versions of Python installed.   To see what Python versions are installed, open the Windows Command Prompt and in the following command:


py --list-paths

Python Version Selection

Note that you can install multiple versions of Python on the same computer.   Unless you specifically select a version to work with, the latest installed version will be automatically selected for you.   You won't experience "installation collisions" by having multiple Python versions installed.   You will however experience library collisions when you have multiple libraries installed.   Use Virtual Environments to more easily isolate the use of one Python version over another, and to manage multiple library installations into a package.  

Before you install Python, you need to select a version that supports your needs.   Your needs will vary from one project to the next, and will typically depend on the libraries you will be using for your project.   The best way to work with different versions of Python and libraries is to create and work within a virtual environment.   If you don't have any plans to use any Python libraries, then visit the Status of Python versions page and choose the latest released Python version, and then download it.  

Suppose you want to work with data science tasks and use the Pandas Python library.   Find the Pandas Python version support page and get the Python versions currently supported.   Repeat this for every library you intend to use (as best you can), and then determine what Python version is supported among all of the libraries you will need.  

TIP: Newer is not always better.   It is typically better to select a Python version somewhere in the middle of the choices, and/or use the Status of Python versions page to assess the status of the Python versions.  

As an example, as of June 2024, Pandas supports Python version 3.9, 3.10, 3.11 and 3.12.   Reviewing the Status of Python versions page, we see that Python versions 3.9, 3.10, 3.11 and 3.12 are all currently supported versions for Pandas version 2.0, and Python version 3.11 will be supported for at least 2.5 years.   Python version 3.11 is probably a safe choice to use with Pandas 2.0.  

IMPORTANT: Do not allow the Python installation to add Python to the Windows path.   You may get warnings about this when upgrading pip later, but using Python will be much more managable without Python added to your Windows path.  


Choosing & Installing an IDE

Installing Python will also install its own Integrated Development Environment (IDE) called 'IDLE'.   I don't recommend using IDLE for beginners, and once you advance to professional development, you will likely use a full feature IDE such as PyCharm or VS Code.   For a Python beginner, I recommend using Thonny.  

Installing Thonny

Thonny is a free, cross platform, open source, lightweight, Python IDE.   From the Thonny home page, you will see a download option.   I recommend selecting the option 'Portable variant with 64-bit Python' for installation on a PC running Windows (this is the least intrusive option in terms of its impact on your OS).   Download the .zip file to your 'Downloads' folder.   Use Windows File Explorer to move the .zip file to a location such as under your 'Documents' folder (I use a folder under 'Documents' named 'portable_apps').   Use Windows File Explorer to extract the .zip file contents to a new folder by right clicking on the file.   Use Windows File Explorer to navigate to the folder containing Thonny and find the 'thonny.exe' executable file.   Use Windows File Explorer to run 'thonney.exe' by double clicking on the file.   Select the appropriate 'Language' and 'Initial settings' options, and then click the 'Let's go!' button.  

Thonny will install a version of Python as part of its installation.   You can see what version is installed by reviewing the contents within the 'Shell' window at the bottom of the Thonny application.   Close the Thonny application by clicking the 'x' at the top right of the application window, or by choosing the menu options 'File'->'Exit'.  

TIP: You can create a shortcut in your Windows start menu to the Thonny application by using File Explorer to find thonny.exe and then right clicking on the file and selecting the option to 'Pin to Start' or perhaps to add a shortcut (varies by Windows OS version).  

Related Links

Thonny IDE User Guide

How to Install and Use Thonny Python IDE on Linux


Configuring a Virtual Environment

A Python Virtual Environment allows you to isolate the use of a particular version of Python and installed libraries.   It is most useful for installing a set of Python packages/libraries for a specific project, without causing them to be installed with your 'global Python installation'.   I am naming a 'global Python installation' the Python version specific installation that is accessible outside of any Virtual Environment (e.g. system-installed Python).   You can only use one Python version and package/library version within a Virtual Environment (you can install multiple Python libraries, but only one version of each).  

PRO TIP: Never install Python libraries to your 'global Python installation'.   Keep your global Python installation clean by always installing libraries within a Virtual Environment.  

Python virtual environments are organized within folders.   It is good practice to have a parent folder named something like 'venv', and then put all of your individual Virtual Environment folders under that folder.  

PRO TIP: Name your Virtual Environment folders something meaningful in terms of its use, such as the project name, or its package content.   Ex. 'venv/pandas2'

Create a Python Virtual Environment

Decide on the Python version and the packages (libraries) you intend to install in your Virtual Environment.   You need only know the package name (that pip recognizes) in order to install it.   You can identify that name and browse available Python packages that can be installed with pip by visiting the Python Package Index at pypi.org.   You can install and uninstall packages at any time within the Virtual Environment, but you should avoid uninstalling packages unless you have a specific problem with a package you are attempting to resolve.  

Python libraries / packages are installed using the Python library/package application pip.   More about pip later.  

Open a Windows Command Prompt window and navigate to the parent folder for your virtual environment folders (e.g. 'venv').  

See what Python versions are installed.  


py --list-paths

If the Python version you need is not installed, then see Installing Python.  

Update pip for the 'global Python installation' Python version you are using (this example will use Python v3.11).   ALWAYS UPDATE PIP before creating a Virtual Environment or installing a Python package.


py -3.11 -m pip install --upgrade pip

Create a new Virtual Environment named 'my_venv', navigate into the folder 'my_venv' (venv will create the folder as part of initializing the virtual environment), and then activate the Virtual Environment by running the command 'activate' from within the 'scripts' folder created by venv, and show the current Python version using the 'py -V' command.  


py -3.11 -m venv my_venv
cd my_venv
scripts\activate
py -V

Note that when you execute the 'activate' command, the command prompt changes to show '(my_venv)' at the beginning of the prompt (before the current folder).   This is a visual way to confirm that the Virtual Environment is active.  

From this point you can install Python packages using the Python library/package application pip.   For example, to install Pandas:


py -m pip install pandas

The Python library/package application pip will install the Pandas package and all dependencies.   Note that the general format for the pip installation command is:


py -m pip install [package name]

You can see what Python packages are installed in the Virtual Environment with the command:


py -m pip list

The above will show that other packages such as 'numpy' that Pandas requires have also been installed.  

When you are done installing packages and using the Virtual Environment, you can deactivate it with the command:


scripts\deactivate

Note that the command prompt has changed and the '(my_venv)' has been removed from the beginning of it.

 

Virtual Environment folders contain a complete set of Python packages for the environment.   The Virtual Environment folder size can get large, and it is therefore not appropriate to include them in any repository such as GitHub.   You can however configure the folder to only allow Python script files (.py) to be backed up to a repository such as GitHub.   Examples on how to do this will be presented later.  

 

Using Virtual Environments With Thonny

Launch the application Thonny.   Select the menu options 'Tools' -> 'Options..', 'Interpreter' tab -> 'Python executable' and navigate to your virtual environment folder.   Within the 'Scripts' subfolder, you will find the file 'python.exe'.   Select the 'python.exe' executable file within your Virtual Environment 'Scripts' folder.  

The Virtual Environment is now active.   You can confirm this in Thommy by the menu options 'Tools' -> 'Open system shell..'.   A Windows Command prompt window will open, and you will see that the Virtual Environment is active by observing the beginning of the command prompt, e.g. (my_venv).  

 

This tutorial is also available on Medium


Scripts

A script is typically a text file that contains programming code.   A script is typically passed as input to a compiler or interpreter in order to run or execute the script.   A Python script is first compiled, and then interpreted.   A uncompiled Python script has a .py filename extension.   A compiled Python script has a .pyc filename extension.  

A code editor is typically used to write a Python .py script file.   More commonly, the code (script) editor is integrated as part of a Integrated Development Environment (IDE) where scripts are created/edited/loaded, compiled, and then executed.   Thonny has an integrated code editor, compiler, and debugger.  

Scripts and libraries (packages) of scripts can be imported partially or in whole and its content made accessible to a script.  

WARNING: Do not name any .py Python script files with a filename that matches the virtual environment folder name, any packages installed, or any Python commands.   If you do, you will experience run time errors that you cannot fix or explain.

Comments In Scripts

Comments in scripts are designated by using the hash character #, and then following that with the comment.   Everything that comes after the hash character on that line is ignored by the compiler.   You can also use triple double quotation marks to denote a block with comments. Triple double quotation marks can be a very useful way to comment out a section of your code, causing the compiler to ignore it.  

PRO TIP: Use only the hash character for comments. That way you can use triple quotation marks to comment out a section of quote, without collision with any comments in your code that already use triple double quotations.  

# single line with a comment
x = 3.1415		# comment following code

""" 
A block of comments.
Can be multiple lines.
"""

Script Template

Below is what I recommend as minimum script content for a Python script.   It is simple to implement, yet provides functionality and legal protection.   The key elements are the copyright notice and the identification of the author, the license, script logging, and the "if __name__ == '__main__':" section.   The section in the code following "if __name__ == '__main__':" only executes when the script is executed outside of being included by another script.   Personally, I find this a good place to do basic development, and to implement tests of any functions that exist in the script, even if those tests are commented out.  


# MIT License
#
# Copyright (c) [year] [author fullname]
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.


# Define the script version in terms of Semantic Versioning (SemVer)
# when Git or other versioning systems are not employed.
__version__ = "0.0.0"
from pathlib import Path
print("'" + Path(__file__).stem + ".py'  v" + __version__)


# Global imports that will be available throughtout the script optionally go here.


# Optionally configure logging
import os.path
from pathlib import Path
import logging
logging.basicConfig(filename=Path(Path.cwd()).joinpath(os.path.basename(__file__).split('.')[0]+".log"), encoding='utf-8', level=logging.DEBUG, format='%(asctime)s %(message)s')
logging.info("Script start.. '" + Path(__file__).stem + "'.py  v" + __version__)


# Functions (optionally) go here.  They are available when the script is included by another script, and to this script. 


if __name__ == '__main__':
    pass

    # This part of the script doesn't execute when the script is included
    # by another script.  It only executes when this script is executed directly.
    
    print("script executed directly (not included)")
    

Syntax

Indentation

Python uses indentation to indicate a block of code (other languages use braces {}, semicolons ; etc.   The indentation (hanging indent) needs to be at least one space, the general convention is to use four spaces, and it should be consistent throughout your code.   Spaces are preferred over tabs.   Example:


if 9 > 7:
    print("The value of 9 is greater than 7")

Variable Names & Style

Start using proper variable naming conventions immediately when you begin learning Python, and it will pay dividends back later.   You can follow the exact Python style guide called PEP 8, but I prefer an approach that is generally compatible with other programming languages.  

Below is a quick reference regarding various style conventions:


module_name, package_name, ClassName, method_name, ExceptionName, function_name, GLOBAL_CONSTANT_NAME, global_var_name, instance_var_name, function_parameter_name, local_var_name

camelCase   StudlyCaps or CapWords or PascalCase   joined_lower_case (snake_case)   Hungarian Notation: arrInputs, sFilePath, iRandomSeed  

Avoid the use of dash '-' in any name.   Double underscore '__' for leading and trailing names (usually they have a reserved purpose).  

Below are short code examples of the convention implemented for Python:


MY_LONG_CONSTANT = 32769

my_variable = "2.5"


def my_function(default_parameter=5):
	""" function documentation
	"""
	return None


class MyClass: 
	"""
	descriptin of MyClass
	"""
	
	def __init__(self, arg_f):
	    self.my_attr_int = 3 
		self.f = arg_f

Code Edit, Compile / Interpret, Debug

You need to be able to create and edit code, compile/run it, and debug it.   Thonny can do that, and much more!   Run the application Thonny.   The primary elements of the graphical user interface (GUI) you need to know are the script editor, run/compile, and the Python Shell.  

Thonny Script Editor

Enter (or copy/paste) the following into the Thonny Script Editor


my_float = 3.14159
my_str = "Pi"
print("\t" + my_str + " is " + str(my_float) + "\n")

Thonny Run/Compile Script

Run (compile) the script and execute it by either pressing the 'F5' key, or clicking on the Thonny toolbar 'Run current script (F5)' toolbar button.   You will see the following output in the Python Shell at the bottom of the Thonny GUI.  


>>> Pi is 3.14159

A complete script example using the script template would appear as:


# MIT License
#
# Copyright (c) [year] [author fullname]
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.


# Define the script version in terms of Semantic Versioning (SemVer)
# when Git or other versioning systems are not employed.
__version__ = "0.0.0"
from pathlib import Path
print("'" + Path(__file__).stem + ".py'  v" + __version__)


# Global imports that will be available throughtout the script optionally go here.


# Optionally configure logging
import os.path
from pathlib import Path
import logging
logging.basicConfig(filename=Path(Path.cwd()).joinpath(os.path.basename(__file__).split('.')[0]+".log"), encoding='utf-8', level=logging.DEBUG, format='%(asctime)s %(message)s')
logging.info("Script start.. '" + Path(__file__).stem + "'.py  v" + __version__)


# Functions (optionally) go here.  They are available when the script is included by another script, and to this script. 


if __name__ == '__main__':
    pass

    my_float = 3.14159
    my_str = "Pi"
    print("\t" + my_str + " is " + str(my_float) + "\n")

If you run the above without saving the script, you will experience an error (see the Python Shell output and the 'Assistant' window contents).  

Save your script and then run it again.   Observe the output in the Shell window.  

In the majority of the examples that follow, the 'script template' will not be shown.   It is not necessary to use this script template for training purposes, but it should be used for any projects you undertake.

The Python Prompt / Shell

The Python installation includes a command line interface (CLI) called the Python Shell application.   This CLI is also known as REPL (Read, Evaluate, Print, Loop).   Most IDE applications like Thonny implement the Python Shell into their GUI.   The Python Shell is the interpreter that executes your Python programs, other pieces of Python code, or simple commands.   The Python Shell has a distinctive prompt:


>>>

You can exit the Python Shell using the same commands used for the Windows Command Prompt and many other terminal applications.   The keystrokes 'CTRL+Z' will terminate the Python Shell, as will the commands 'quit' or 'exit'


>>> quit

>>> exit

Related Links

Run Python Script – How to Execute Python Shell Commands in the Terminal


Print

The Python print() function outputs a message to a standard output device, typically the Python Shell.  

The print() function syntax varies slightly by Python version, but generally it is:


*objects, sep=' ', end='\n', file=None, flush=False

The output of the print() function goes to sys.stdout by default, which is typically the the Python Shell.  

You can find a lot of alternatives to the print() function, and ways to pass content to the print() function such as 'f-strings' and the Modulo Operator (%).   I recommend using the Python print() function in a manner that is similar to implementations used by other programming languages:  

  • Convert (cast) all content (variables, objects, etc) to be printed to strings.
  • Use the Python concatenation operator (+) to join multiple items in a single print() output.
  • Use '\t' for tabular indentation, and '\n' for a new line.

Example:


my_float = 3.14159
my_str = "Pi"
print("\t" + my_str + " is " + str(my_float) + "\n")

Output from the above to the Python Shell:


>>> Pi is 3.14159

In the example above, the Python built-in str() function is used to convert the contents of the variable 'my_float' from a floating point number, to a string.   It also has extensive methods for formatting the string output.  


Variables & Data Types

Unlike many programming languages, Python doesn't require you to declare and initialize variables before using them.   Python variables are created as soon as you make an assignment.   Variables are containers that hold data values.   Variable naming conventions were already discussed.  


my_float = 3.14159
my_integer = 123
my_str = "Pi"
print("my_str: " + my_str + "\t data type: " + str(type(my_str)))
print("my_float: " + str(my_float) + "\t data type: " + str(type(my_float)))
print("my_integer: " + str(my_integer) + "\t data type: " + str(type(my_integer)))

Python has a number of built-in data types.   The data type defines what type of data may be stored in the variable.   The prior example demonstrates integer, float, and string data types.   Python also has built-in boolean, binary, complex, None, and structure data types (list, tuple, range, dict, and set).   Many modules are available to support other data types such as datetime.   As demonstrated above, the type() function returns the data type passed as its argument.  

WARNING: When dealing with very large and small integer and floating point numbers, the minimum and maximum value the variable data type can support varies depending on the Python version, and if the Python compiler is run on a 32-bit or 64-bit system.   This is the same situation for most programming languages.   See Everything You Need to Know About Python's Maximum Integer Value for more information.  

Strings

A Python string is a sequence of characters.   Strictly speaking, they are an array of bytes representing Unicode characters.  


str_one = "My string one"
str_two = 'My string two'
str_three = """My string three"""
print("str_one: '" + str_one + "'")
print("str_two: '" + str_two + "'")
print("str_three: '" + str_three + "'")
print("concatenation: " + str_one + str_two + str_three)

Output:


str_one: 'My string one'
str_two: 'My string two'
str_three: 'My string three'
concatenation: My string oneMy string twoMy string three

Structures / Collections

The structure built-in data types include list, tuple, range, dict, and set.   When I was first learning Python, I struggled with determining which structure data type to use.   Start with using dictionarys and lists first, and then evolve using the other data types as you become more experienced.   The table below should help, although it doesn't address big code project considerations such as speed of execution and data storage memory requirements.  

Data Type Usage Considerations
Dictionary Key / value pairs (mappings).   The key as a string, numeric, etc must be unique.   Mutable.  
List Mixed data types where you want to be able to add, remove, sort, count items, and iterate over.   Mutable.  
Tuple Immutable list of mixed data types.   Use when you need fast execution.  
Set Mutable unordered unique collection of values of the same data type that are iterable.  
Array Mutable collection of items of the same data type.  

You will often hear the term 'mutable' and 'immutable' when variable / object data types are discussed.   Mutable data types / objects can be changed (data contents) after their assignment.   Immutable data types / objects cannot be changed after their assignment.   Note however that although a data type or object is immutable, they typically have methods that allow appending and other changes to their contents.  

Dictionary


animals = {}        # initialize an empty dictionary
animals['cat'] = "Oliver"
animals['dog'] = "Bruno"
animals['snake'] = "Monty"
# The print() statement below shows how to access the value in the dictionary for the key = 'dog'
print("My dog's name is: " + animals['dog'])

# Another way to initialize a dictionary
animals = {
	'cat': 'Oliver',
	'dog': 'Bruno',
	'snake': 'Monty'
}

# Check for existance of a key:
if 'dog' in animals:
	print("Key 'dog' found in dictionary 'animals'")
else:
	print("Key 'dog' NOT found in dictionary 'animals'")

# Change the value of a dictionary by key:
animals['dog'] = 'Fido'
print("My dog's name is: " + animals['dog'])

# Access the keys of a dictionary
print("\nkey in animals.keys():")
print(animals.keys())       # .keys() returned as a list
for key in animals.keys():
	print("\t" + key)

# Dictionary keys cannot be changed/renamed. Create new and delete original.
animals['best_friend'] = animals['dog']
#del animals['dog']     # Delete key/value using del command
animals.pop('dog')      # Delete key/value using .pop method
# Below raises an error because key 'dog' doesn't exist
try:
	print("\nanimals['dog']: " + animals['dog'])
except Exception as e:
	print("\nERROR: while attempting to access key " + str(e) + "  (key/value has been deleted)")
print("animals['best_friend']: " + animals['best_friend'])

# Delete any variable
del animals

# A dictionary with integers for the key
int_dict = {
	65: "A",
	66: "B",
	67: "C"
}
# Iterate over the dictionary contents
print("\nint_dict:")
for key in int_dict:
	print(str(key) + "\t" + int_dict[key])

Output:


My dog's name is: Bruno
Key 'dog' found in dictionary 'animals'
My dog's name is: Fido

key in animals.keys():
dict_keys(['cat', 'dog', 'snake'])
        cat
        dog
        snake

ERROR: while attempting to access key 'dog'  (key/value has been deleted)
animals['best_friend']: Fido

int_dict:
65      A
66      B
67      C

List


my_li = []      # initialize an empty list
my_li.append(1)
my_li.append("two")
my_li.append(3.14)
# Iterate over the list
print("\nmy_li:")
for item in my_li:
	print("\t" + str(item))

my_li = [1, "two", 3.14]    # initialize the list immediately
print("\nmy_li enumerate():")
for i, val in enumerate(my_li):
	print("\t" + str(i) + "\t" + str(val))

# Change the value of the list my_li at index 1.  List index starts at zero. 
my_li[1] = "position two"

# List index starts at zero. So the second item in the list has an index of 1.
print("\nThe second item in my_li is '" + str(my_li[1]) + "'")

# Function len() returns the length of a variable
print("\nlen(my_li): " + str(len(my_li)))

# Remove second item (index 1) in list my_li
my_li.pop(1)
print("\nmy_li.pop(1)")
# Below is another way to iterate over a list using the range() iterable function. 
for i in range(0,len(my_li)):
	print(str(i) + "\t" + str(my_li[i]))
# IMPORTANT: Note that my_li has been re-indexed after the removal of the 2nd item. 

numeric_li = [0.5, 0.8, 0.2]
print("\nnumeric_li: " + str(numeric_li))
numeric_li.sort()
print("\nnumeric_li sorted: " + str(numeric_li))

print("\n0.5 in numeric_li: " + str(0.5 in numeric_li))
print("0.3 not in numeric_li: " + str(0.3 not in numeric_li))

Output:


my_li:
        1
        two
        3.14

my_li enumerate():
        0       1
        1       two
        2       3.14

The second item in my_li is 'position two'

len(my_li): 3

my_li.pop(1)
0       1
1       3.14

numeric_li: [0.5, 0.8, 0.2]

numeric_li sorted: [0.2, 0.5, 0.8]

0.5 in numeric_li: True
0.3 not in numeric_li: True

The examples above show the basics for dictionaries and lists.   Many more of methods are available for dictionaries and lists than demonstrated.  

Date / Time


import datetime

now = datetime.datetime.now()
mm = str(now.month)
dd = str(now.day)
yyyy = str(now.year)
hour = str(now.hour)
mi = str(now.minute)
ss = str(now.second)
print(mm + "/" + dd + "/" + yyyy + " " + hour + ":" + mi + ":" + ss)
# 8/23/2023 6:0:56

# Get each day of the month, every month of the year
from datetime import datetime
import calendar
for m in range(1,13):
	for d in range(1, calendar.monthrange(2010, m)[1]+1):
		print(datetime(2010, m, d).strftime("%Y-%m-%d"))
		# if datetime(year, m, d).weekday() < 5: print(datetime(year, m, d).strftime("%A %Y-%m-%d"))  # Get weekday only

#2010-01-01
#2010-01-02
#2010-01-03
#...
#2010-12-30
#2010-12-31

# Iterate over days / weekdays between two dates
import datetime
start_date = datetime.date(2021, 2, 1)
end_date = datetime.date(2021, 2, 17)
delta = datetime.timedelta(days=1)
# iterate days between start_date and end_date
while (start_date <= end_date):
    print(start_date.strftime("%Y-%m-%d  %A"))
    #if start_date.weekday() < 5: print(start_date.strftime(" %Y-%m-%d  %A"))  # weekdays only
    start_date += delta

# DateTime to Unix timestamp in UTC Timezone

import datetime

date = datetime.datetime.utcnow()
utc_time = calendar.timegm(date.utctimetuple())
print(utc_time)
#1677569634

utc_time = calendar.timegm(datetime.datetime.utcnow().utctimetuple())
print(utc_time)
#1677569634

# DateTime to Unix timestamp milliseconds
import datetime
import time
ms = time.mktime(datetime.datetime.now().timetuple()) * 1000
print(ms)
#1677569729000.0

# ISO 8601
import datetime

print("date/time ISO8601 in seconds: ", datetime.datetime.now().isoformat(timespec="seconds"))
print("date/time ISO8601 in milliseconds: ", datetime.datetime.now().isoformat(timespec="milliseconds"))
print("date/time ISO8601 in microseconds: ", datetime.datetime.now().isoformat(timespec="microseconds"))

# ISO8601 datetime string to datetime object

import datetime
from zoneinfo import ZoneInfo
utc = ZoneInfo('UTC')

start = "2024-01-02T19:54:05.753Z"
end = "2024-01-02T20:17:06.620Z"

start = datetime.datetime.strptime(start, "%Y-%m-%dT%H:%M:%S.%fZ")
end = datetime.datetime.strptime(end, "%Y-%m-%dT%H:%M:%S.%fZ")
time_delta = (end-start)
print("duration:", time_delta)
print("duration [sec]:", time_delta.total_seconds())

# Datetime.date to Unix timestamp
import datetime
now = datetime.datetime.now()
my_datetime = datetime.date(now.year, 8, 6)
print("Unix_Time: ",(time.mktime(my_datetime.timetuple())))
#Unix_Time:  1691294400.0

# Unix timestamp to Python DateTime
import datetime

# assigned unix time
unix_time = 1627334400
date_time = datetime.datetime.fromtimestamp(unix_time)
# print unix time stamp
print("Unix_Time =>",unix_time)
# displaying date and time in a regular
# string format
print("Date & Time =>" ,date_time.strftime('%Y-%m-%d %H:%M:%S'))
#Unix_Time => 1627334400
#Date & Time => 2021-07-26 17:20:00

unix_ms = 1724443737000.0 
unix_ms = datetime.datetime.fromtimestamp(unix_ms/1000.0, tz=datetime.timezone.utc)
print(unix_ms)
# 2024-08-23 20:08:57+00:00


# Convert datetime string in ISO8601 format to datetime object

from datetime import datetimeS

date_time_iso8601 = "2024-08-23T16:08:57.604388+00:00"
date_time_iso8601 = datetime.strptime(date_time_iso8601, "%Y-%m-%dT%H:%M:%S.%f%z")
print(date_time_iso8601, type(date_time_iso8601))
# 2024-08-23 16:08:57.604388+00:00 


# Check the difference between two dates and correct them to be at most 10 years

from datetime import datetime
from dateutil.relativedelta import relativedelta
# 2010-01-01 2010-12-01
startdate = "2001-01-01"
enddate = "2010-12-01"

# Convert date string to a datetime object
# strptime(date_str, format)
start = datetime.strptime(startdate, "%Y-%m-%d")
end = datetime.strptime(enddate, "%Y-%m-%d")
if start > end: raise Exception("ERROR: date " + str(start) + " comes after " + str(end))
diff = abs((end-start).days)
#print(round(diff/365,1), " years")
if diff > 10.0:
    # Adjust enddate to be 10 years from startdate
    end = start + relativedelta(years=10)
    enddate = datetime.strftime(end, "%Y-%m-%d")
print(startdate, enddate)

The None Data Type

The Python None data type is used for representing a variable with no value, or the absence of a value assignment.   Note that this is not the same as NaN (Not a Number) that can occur for numbers, where a numerical value is expected, but no value is assigned.   Null in other programming languages is used to denote the absence of a value, but not in Python.  

When Python interacts with other systems such as a database, the returned value(s) may include Null values.   Typically in those cases, the library or the driver that interacts with the database will convert those Null values to the Python None value.   Some libraries/packages such as Numpy and Pandas have their own way of handling None/Null values, so watch out for those.  

Below are two examples where a function returns None.


def my_fn():
	return None


def my_fn_pass():
	pass

a = my_fn()
if a is None:
	print("a is None")
else:
	print("a is NOT None")

b = my_fn_pass()
if b is None:
	print("b is None")
else:
	print("b is NOT None")

Output:


a is None
b is None

Comparison Operators

Comparison operators are used to compare two values.  


x = 5
y = 8

if x == 5:
	print("x equals 5")

if x != 3:
	print("x not equal to 3")

print("\nif, elif, else:")
if x == y:
	print("x equals y")
elif x >= y:
	print("x >= y")
else:
	print("x < y")

fruit1 = "apple"
fruit2 = "orange"
print("\nfruit1, fruit2")
if fruit1 == fruit2:
	print("fruit1 == fruit2")
else:
	print("fruit1 != fruit2")

a = 0.1
b = 0.2
import math
print("\nmath.isclose(x, y): " + str(math.isclose(a+b, 0.3)))

f_nan = float('nan')
itgr = 5
inf = float('infinity')
print("\nmath.isnan(f_nan): " + str(math.isnan(f_nan)))
print("math.isnan(itgr): " + str(math.isnan(itgr)))
print("math.isnan(inf): " + str(math.isnan(inf)))
print("inf > itgr: " + str(inf > itgr))
print("inf > f_nan: " + str(inf > f_nan))

# Logical operators and, or, not
t = True
f = False
print("t and f: " + str(t and f))
print("t or f: " + str(t or f))
print("not t: " + str(not t))

Output:


x equals 5
x not equal to 3

if, elif, else:
x < y

fruit1, fruit2
fruit1 != fruit2

math.isclose(x, y): True

math.isnan(f_nan): True
math.isnan(itgr): False
math.isnan(inf): False
inf > itgr: True
inf > f_nan: False

t and f: False
t or f: True
not t: False

Flow Control

Conditionals

if, elif, else


if condition:
	# executes if condition is true
elif condition:
	# executes if condition is true
elif condition:
	# executes if condition is true
else:
	# executes if neither of the prior conditions are true

match

The match statement compares a variables value to one or more patterns.   The example below compares a numerical value, but the variable 'status' could be a string, a list or other type of variable that has a unique set of values (e.g. not a floating point variable).  


status = 400
match status:
	case 400:
		print("Bad request")
	case 401 | 403 | 404:
		# The | acts as a logical OR
		print("Out of range")
	case 405:
		print("Not found")
	case _:
		# _ acts as a wildcard, effectively an else
		print("Unexpected value of '" + str(status) + "' for status")

Jump statements

The break and continue statements interrupt a flow.   The break statment terminates the current loop and resumes execution at the statement following the loop.   The continue statement skips the current loop execution, and returns to the start of the loop (continues the loop with the next iterable value).  


i = 0
while True:
	i += 1      # increment the value of i by 1
	if i == 3:
		continue
	elif i > 5:
		break
	print("\ti = " + str(i))
print("i: " + str(i))

Output:


        i = 1
        i = 2
        i = 4
        i = 5
i: 6

Note that "i = 3" is not printed because the continue statement causes the loop to return to the beginning of the loop, skipping the print() statement.   The loop terminates when i == 6 because of the break statement.  

Loops & Iteration

for, range() & enumerate()


# Use for to iterate over a list.
prime_nos = [1, 3, 5, 7]
print("prime_nos:")
for prime in prime_nos:
	print("\t" + str(prime))


# The enumerate() function returns the index during the iteration, and it allows you to select the starting index
print("\nenumerate():")
for idx,prime in enumerate(prime_nos, start=1):
	print("\t" + str(idx) + "\t" + str(prime))

# The Python range() function returns a list for the specified range of values
print("\nrange(3, 0, -1):")
# range(start, end, step)
for i in range(3, 0, -1):
	print("\t" + str(i))
# IMPORTANT: Note that zero is not output.  range() returns a list just shy of the stop value


print("\nrange(3, -1, -1):")
for i in range(3, -1, -1):
	print("\t" + str(i))

Output:


prime_nos:
        1
        3
        5
        7

enumerate():
        1       1
        2       3
        3       5
        4       7

range(3, 0, -1):
        3
        2
        1

range(3, -1, -1):
        3
        2
        1
        0

These are the interation basics only.   See also iter(), list comprehensions, zip(), filter(), map, sorted().  

while


i = 1
while (i < 5):
	print("\tin loop, i: " + str(i))
	i += 1      # increment the value of i by 1
print("i: ", str(i))

Output:


        in loop, i: 1
        in loop, i: 2
        in loop, i: 3
        in loop, i: 4
i:  5

IMPORTANT: Note that the variable 'i' above has a value of 5 when it exits the loop.  

Another example using continue and break statements:


i = 0
while True:
	i += 1      # increment the value of i by 1
	if i == 3:
		continue
	elif i > 5:
		break
	print("\ti = " + str(i))
print("i: " + str(i))

Output:


        i = 1
        i = 2
        i = 4
        i = 5
i: 6

Errors & Exceptions


# Simple exception (error) handling using try/except
nos = [3, 2, 0, 5]   
print("Divide 1 by nos:")
for num in nos:
	try:
		print("\t1/" + str(num) + " = \t" + str(1/num))
	except Exception as e:
		print("\t1/" + str(num) + " = \t" + str(e))


# except ZeroDivisionError
print("\nDivide 1 by nos:")
for num in nos:
	try:
		print("\t1/" + str(num) + " = \t" + str(1/num))
	except ZeroDivisionError:
		print("\t1/" + str(num) + " = \t DIVISION BY ZERO NOT ALLOWED")
	except Exception as e:
		print("\t1/" + str(num) + " = \t" + str(e))

del nos
nos = [3, 2, 0, 5, None, 'A', float('nan'), float('infinity'), 6]   
print("\nDivide 1 by nos:")
for num in nos:
	try:
		print("\t1/" + str(num) + " = \t" + str(1/num))
	except ZeroDivisionError:
		print("\t1/" + str(num) + " = \t DIVISION BY ZERO NOT ALLOWED")
	except Exception as e:
		print("\t1/" + str(num) + " = \t" + str(e))


# You can raise an exception too
print("\nitems:")
items = [4, 5, 3.1415, 6]
for item in items:
	# The isinstance() function checks if a variable is of a particular data type
	if not isinstance(item, int): 
		raise Exception("item '" + str(item) + "' is not a value of data type integer")
	else:
		print("\t" + str(item))

Output:


Divide 1 by nos:
        1/3 =   0.3333333333333333
        1/2 =   0.5
        1/0 =   division by zero
        1/5 =   0.2

Divide 1 by nos:
        1/3 =   0.3333333333333333
        1/2 =   0.5
        1/0 =    DIVISION BY ZERO NOT ALLOWED
        1/5 =   0.2

Divide 1 by nos:
        1/3 =   0.3333333333333333
        1/2 =   0.5
        1/0 =    DIVISION BY ZERO NOT ALLOWED
        1/5 =   0.2
        1/None =        unsupported operand type(s) for /: 'int' and 'NoneType'
        1/A =   unsupported operand type(s) for /: 'int' and 'str'
        1/nan =         nan
        1/inf =         0.0
        1/6 =   0.16666666666666666

items:
        4
        5
Traceback (most recent call last):
  File "..\venv\my_venv\tutorial_part2.py", line 90, in 
    raise Exception("item '" + str(item) + "' is not a value of data type integer")
Exception: item '3.1415' is not a value of data type integer

Functions

Before you build a custom function, stop and research, because what you need is very likely already available in a library.   Visit the Python Package Index at pypi.org.  

A function is a block of code that only runs when called.   You can pass data to a function as parameters / arguments.   A function can return a data.   You can use functions to break up large code projects into smaller chunks (see also libraries).   Use the def keyword to define a function.   Call a function by name, making sure to include the parenthesis.  


def my_fn():
	# A simple function with no arguments/parameters.  No data returned.
	print("Function 'my_fn()' has been called")

# Call the function my_fn():
my_fn()

Output:


Function 'my_fn()' has been called

Function Arguments & Return Value(s)

Data can be passed to a function as arguments/parameters within the parethesis that follow a function definition with def.   Separate multiple function arguments with a comma (,).   It is a best practice to use keyword arguments with the key=value syntax.   Whenever possible, it is also best to supply a default value for the function arguments.   You can pass any data type as an argument to a function (integer, float, list, dictionary, ..).   A function can optionally return one or more values (data).


def build_rec(place_name="", latitude=None, longitude=None, verbose=False):
	# Returns a dictionary built from the passed arguments

	# Validate the arguments
	if not isinstance(place_name, str) or len(place_name)==0: raise Exception("place_name passed to fn " + build_rec.__name__ + "() is invalid")
	if not isinstance(latitude, float): raise Exception("latitude passed to fn " + build_rec.__name__ + "() is invalid")
	if not isinstance(longitude, float): raise Exception("longitude passed to fn " + build_rec.__name__ + "() is invalid")
	
	# Build the record from the arguments as a dictionary
	rec = {}
	rec['name'] = place_name
	# Use the hash() function to convert place_name to a hash, and then the hex() function to conver the integer to a hexadecimal value.
	rec['hash'] = hex(hash(place_name))
	rec['latitude'] = round(latitude,5)
	rec['longitude'] = round(longitude,5)

	if verbose: print(rec)

	return rec



recs = []

rec = build_rec(place_name="Zebra Slot", latitude=37.756682020599186, longitude=-111.40772372019913)
recs.append(rec)
print("recs: " + str(recs))
print("\n")

rec = build_rec(place_name="Antelope Canyon", latitude=36.86780725531749, longitude=-111.37415524285456, verbose=True)
recs.append(rec)
print("recs: " + str(recs))
print("\n")

# Below raises an exception
rec = build_rec(place_name="", latitude=36.86780725531749, longitude=-111.37415524285456)
recs.append(rec)
print("\n")

Output:


recs: [{'name': 'Zebra Slot', 'hash': '0x528dc84df304ee99', 'latitude': 37.75668, 'longitude': -111.40772}]


{'name': 'Antelope Canyon', 'hash': '0x32720a2d213a5c0', 'latitude': 36.86781, 'longitude': -111.37416}
recs: [{'name': 'Zebra Slot', 'hash': '0x528dc84df304ee99', 'latitude': 37.75668, 'longitude': -111.40772}, {'name': 'Antelope Canyon', 'hash': '0x32720a2d213a5c0', 'latitude': 36.86781, 'longitude': -111.37416}]      


Traceback (most recent call last):
  File "..\venv\my_venv\tutorial_part2.py", line 88, in 
    rec = build_rec(place_name="", latitude=36.86780725531749, longitude=-111.37415524285456)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "..\venv\my_venv\tutorial_part2.py", line 57, in build_rec
    if not isinstance(place_name, str) or len(place_name)==0: raise Exception("place_name passed to fn " + build_rec.__name__ + "() is invalid")
                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Exception: place_name passed to fn build_rec() is invalid

You can also employ arbritary keyword arguments (**kwargs), and use recursion.  

Generators

A generator function in Python creates a range of values and returns them using the yield statement.   Generator functions can be used as an interator and called by the for statement.  


def factorial_gen(limit=None):
	# Returns successive factorials beginning at n=0

	import math

	if limit is None: raise Exception("Argument 'limit' not specified for fn " + factorial_gen.__name__)

	i = 0
	while i < limit:
		yield math.factorial(i)
		i += 1


for f in factorial_gen(5):
	print("\t" + str(f))

Output:


        1
        1
        2
        6
        24

More on generators


Libraries / Packages / Modules / Projects

A script is a Python file that is intended to be run directly.   When you import a script into another script using the import statement, then the imported script becomes a module.  

A module is a Python script that is intended to be imported by other scripts via the import command.  

A package is a group of related modules that together provide a specific functionality.   The modules are contained within a folder, and they contain a special __init__ file that identifies to Python that the folder contains a package.  

A library is an alias for modules and packages.   The term 'library' is commony used in other programming languages.  

PIP is Python package (library) manager.

WARNING: Do not name any .py Python script files with a filename that matches the virtual environment folder name, any packages installed, or any Python commands.   If you do, you will experience run time errors that you cannot fix or explain.

The Table / Spreadsheet / Database Paradigm

Many 2D and 3D data storage structures can be thought of in terms of a table, spreadsheet, or database.   The two dimensional (2D) paradigm consists of a table (shown below), a spreadsheet sheet (single tab), or a single database table.   The table has horizontal columns, and vertical rows.   In a spreadsheet, the columns are labeled "A", "B", "C", .. and the rows from 1 to n.  

  Column 1 Column 2 Column 3
row 1      
row 2      
row 3      

 

A third dimension (3D) can be derived for a spreadsheet and a database.   A spreadsheet can have multiple sheets in a workbook, and those sheets may reference columns/rows from different sheets.   A database can have multiple tables, and the tables may be linked by various indexes.  

Math

Operators


a = 33
b = 4
c = 2

r = a + b - c
print("\nr = " + str(r))
# r = 35

# integer (floor) division
r = a // b
print("\na // b = " + str(r))
# a // b = 8

r = a / b
print("\na / b = " + str(r))
# a / b = 8.25

r = 4**2
print("\n4**2 = " + str(r))
# 4**2 = 16

# The modulus % operator returns the remainder after a division (Euclid’s Division Lemma)
r = a % b
print("\na % b = " + str(r))
# a % b = 1

Output:


r = 35

a // b = 8

a / b = 8.25

4**2 = 16

a % b = 1

The modulus % operator seems like an odd operator, but it actually solves a number of programming application problems.   From the above example, you see that a % b = 1, or 33 % 4 = 1.   Below shows 4 divided into 33 using 8 (4*8=32), and the remainder after subtracting 32 from 33 is 1.  

Above is the basics.   See more at Python - Operators.  

Python math Module

The Python math module has a wide variety of math functions.   Visit w3schools.com/python/module_math.asp for a well presented list of the module contents.  

SciPy is a popular open source library for scientific computing.

Data Science

If your data doesn't consist of time series data and you want to build a machine learning (ML) model, see Data Science by Example.   For using machine learning for time series forecasting, take a close look at Darts by Unit8.  


This tutorial is also available online as Python Beginner Guide — Part 1 and Python Beginner Guide — Part 2.