The Python Tutorial

I wanted to go through the Python Tutorial to review base Python. In this notebook, I mainly took notes on things I wanted to review or things I wanted to get a clearer defintion of.

The Python Tutorial

Python is an easy to learn, powerful programming language. It has efficient high-level data structures and a simple but effective approach to object-oriented programming. Python's elegant syntax and dynamic typing, together with its interpreted nature, make it an ideal language for scripting and rapid application development in many areas on most platforms.

Glossary

argument

  • A value passed to a function (or method) when calling the function. Two kinds:
  1. keyword argument: an argument preceded by an identifier (e.g. name=) in a function call or passed as a value in a dictionary preceded by **. For example, 3 and 5 are both keyword arguments below:
complex(real=3,imag=5)
complex(**{'real': 3, 'imag': 5})
  1. positional argument: an argument that is not a keyword argument. Positional arguments can appear at the beginning of an argument list and / or be passed as elements of an iterable preceded by *. or example, 3 and 5 are both keyword arguments below:
complex(3, 5)
complex(*(3, 5))
  • Arguments are assigned to the named local variables in a function body.

Bytecode

Python source code is compiled into bytecode, the internal representation of a Python program in the CPython interpreter. The bytecode is also cached in .pyc files so that executing the same file is faster the second time. This "intermediate language" is said to run on a virual machine that executes the machine code corresponding to each bytecode.

decorator

A function returning another function, usually applied as a function transformation using the @wrapper syntax. The decorator syntax is merely sntactic sugar, the following two function definitions are semantically equivalent:

def f(arg):
  pass

@staticmethod
def f(arg):
  pass

docstring

A string literal which appears as the first expression in a class, function, or module. While ignored when teh suite is executed, it is recognized by the compiler and put into the __doc__ attribute of the enclosing class/function/module.

function annotation

An annotation of a function or parameter or return value. Function annotations can be used for type hints:

def sum_two_ints(a: int, b: int) -> int:
  return a + b

immutable

An object with a fixed value. Immutable objects include numbers, strings, and tuples. Such an object cannot be altered.

iterable

An object capable of returning its members one at a time. Examples of iterables include all sequece types (such as lust, str, and tuple) and some non-sequence types like dict and file objects.

lambda

An anonymous inline function consisting of a single expression which is evaluated when the function is called. The syntax to create a lambda function is lambda [parameters]: expression.

mutable

Mutable objects can change their value but keep their id().

namespace

The place where a variable is stored. Namespaces are implemented as dictionaries. There are the local, global, and built in namespaces as well as nested namespaces in objects. Namespaces support modularity by preventing name conflicts.

parameter

A named entity in a function (or method) definition that specifies an argument that the function can accept. Five kinds:

  1. positional-or-keyword: specifies an argument taht may be passed either positionally or as a keyword argument. The default kind of parameter. foo and bar in the following:
def func(foo, bar=None):
  pass
  1. positional-only: specifies an argument that can be supplied only by position. Position only parameters can be defined by including a / character in the parameter list of the function definition after thm, for example posonly1 and posonly2 below:
def func(posonly1,posonly2,/,positional_or_keyword=None):
  pass
  1. keyword-only: specifies an argument that can be supplied only by keyword. Keyword-only parameters can be defined by including a single var-positional parameter or bare * in the parameter list of the function definition before them, for example kw_only1 and kw_only2 below:
def func(arg,*,kw_only1,kw_only2):
  pass
  1. var-positional: specifies that an arbitrary sequence of positional arguments can be provided (in addition to any positional arguments already accepted by other parameters). Such a parameter can be defined by prepending the parameter name with *, for example args in the following:
def func(*args,**kargs):
  pass
  1. var-keyword: specifies that arbitrarily many keyword arguments can be provided (in addition to any keyword arguments already accepted by other paraeters). Such a parameter can be defined by prependung the parametre name with **, for example kargs in the example above.

slice

An object usually containing a portion of a sequence. A slice ic created using the subscript notation [], with colons between numbers when sever are given, such as in variable_name[1:3:5].

import this
out[2]

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Using the Python Interpreter

The Python interpreter is usually installed as /usr/local/bin/python3.12 on those machines where it is available. Typing the end-of-file character (CTRL+D on Unix, CTRL+Z on Windows) at the primary prompt causes the interpreter to exit with a zero status. You can also try typing quit(). By default, Python source files are treates as encoded in UTF-8.

An Informal Introduction to Python

If you don't want characters prefaced by "" to be interpreted as special characters, you can use raw strings by adding an r before the first quote. Strings can be concatenated with the + operator, and repeated with *. Two or more string literals next to each are automatically concatenated. Strings can be indexed, with the first charcter having index 0. Attempting to use an index that is too large will result in an IndexError.

Python knows a number of compound data types, used to group together other values. The most versatile is list, which can be written as a list of comma-separated values (items) between sequare brackets. All slice operations return a new list containing the requested elements.

"""
Numbers
"""
def print_math(exp):
  print(exp)
print_math((2+2))
print_math((2**3))
print_math((16 - 4))
print_math(( 16 // 3 ))
print_math((16 % 3 ))
print_math((5 ** 3))
"""
Text
"""
print(r"Hello World. Backslash: \ ")
print('Hello '
      'World')
word = "pneumonoultramicroscopicsilicovolcanoconiosis"
print(word[0])
print(word[-2:])
print(word[10:-10])

"""
Lists
"""
a = [1,2,3,"Hello","World",[5,6,7]]
print(a)
print(a[2])
a.append(67.62)
print(a)
print(len(a))
out[5]

4
8
12
5
1
125
Hello World. Backslash: \
Hello World
p
is
tramicroscopicsilicovolca
[1, 2, 3, 'Hello', 'World', [5, 6, 7]]
3
[1, 2, 3, 'Hello', 'World', [5, 6, 7], 67.62]

Control Flow Statements

x = input("Please enter an integer:\t")
try:
  x = int(x)
except ValueError:
  import math
  x = math.inf
if x == math.inf:
  print("Please enter a valid number")
elif x < 0:
  x = 0
  print("Negative changed to 0")
elif x==0:
  print("Zero")
elif x==1:
  print("Single")
else:
  print("More")
out[7]

Please enter an integer: uhefdh
Please enter a valid number

def http_error(status):
  match status:
    case 200 | 301:
      return "Success or Redirected"
    case 400:
      return "Bad Request"
    case 404:
      return "Not Found"
    case 418:
      return "I'm a teapot"
    case _: # This acts like the default case
    # The variable name _ acts a wildcard and never fils to match
      return "Something is wrong with the Internet"
out[8]

Modules

A module is a file containing Python definitions and statements. The file name is the module name with the suffix .py appended. Within a module, the module's name (as a string) is available as the value of the global variable __name__.

Virtual Environment and Packages

Python applications will often use packages and modules that don't come as part of the standard library. Applications will sometimes need a specific version of a library, because the application may require that a particular bug has been fixed of the application may be weitting using an obsolete version of the library's interface.

The solution for this problem is to create a vitual environment, a self-contained directory tree that contains a Python installation for a particular version of Python, plus a number of additional packages.

Different applications can then use different virtual environments. To create a virtual environment, decide upon a directory where you want to place it, and run the venv module as a script with a directory path.

python -m venv tutorial-env

The command above will create the tutorial-env directory if it doesn;t exist, and also create directories inside it containing a copy of the Python interpreter and various supporting files.

A common directory for location for a virtal environment is .env. This name keeps the directory typically hidden in your shell and thus out of the way while giving it a name that explains why the directory exists. It also prevents clashing with .env environment variable definition files that some tooling supports.

Activating an environment on unix:

source tutorial-env/bin/activate

Activating a virtual environment will change your shell'd prompt to show what virtual environment you're using, nand modify the environment so that running python will get you that particular version of Python.

Deactivate Python:

deactivate