andersch.dev

<2024-10-26 Sat>

Python

Python is a dynamically-typed, interpreted programming language. It has gained widespread use due to its resemblance to pseudo-code and numerous libraries.

Python Package Manager

Pip Installs Packages (pip):

  • pip is the most widely used package manager for Python.
  • Comes pre-installed with Python >3.4
  • Installs packages from the Python Package Index (PyPI)
  • Usage
    • pip install package_name
    • pip uninstall package_name
    • pip list
    • pip install --upgrade package_name

virtualenv:

  • virtualenv is a tool for creating isolated Python environments.
  • Allows managing of dependencies for projects separately
  • Usage:
    • virtualenv env_name
    • source env_name/bin/activate (Activate virtual environment)

pipenv:

  • pipenv combines pip and virtualenv
  • Uses a Pipfile to specify dependencies and a Pipfile.lock for version locking.
  • Usage:
    • pipenv install
    • pipenv install package_name
    • pipenv uninstall package_name
    • pipenv shell (Activate virtual environment)

uv:

  • Fast Python package manager and resolver
  • Drop-in replacement for pip, pip-tools, virtualenv
  • handles virtual environments natively
  • Single binary written in Rust
  • unified CLI for tasks like uv pip install, uv venv, or uv python
  • Manages projects with a pyproject.toml file
  • uvx (alias for uv tool run) for executing scripts in isolated environment

Compiling Python

Python by default is not compiled to an executable nor JIT-compiled to machine code. Instead, the standard interpreter CPython compiles a given python script to bytecode that can be run line-by-line by the Python Virtual Machine (PVM).

To compile Python to bytecode: python -m py_compile source.py

The compiled bytecode will be in the __pycache__ directory. To execute it from the command line: python -m source

However, there are tools to compile python code.

Cython:

  • translates Python code to C/C++ code
  • supports calling C functions and declaring C types

PyPy

  • Python implementation with a JIT compiler.
  • Runtime optimisations, fully language compliant
  • Can run most Python code, except for CPython extensions
  • PyPy's meta-tracing toolchain is called RPython.
  • Uses meta-tracing: takes interpreter as input and produces a tracing just-in-time compiler as output.

Type Checking in Python

Python supports type hinting since version 3.5:

import typing

# primitive type hints
def add(a: int, b: int) -> int:
    return a + b
x : int = add(4,5)
print(x)

# type hints for lists (or tuples, dicts)
def get_floats(input : list[float]) -> list[float]:
    floats : list[float] = [3.4, 2.8, 2.5, 3.9]
    result = [input[i] + floats[i] for i in range(len(input))]
    return result
print(get_floats([3.5,2.8,3.1]))

# union type hints (allow more than one type)
def sum_ab(a: int | float, b: int | float) -> int | float:
    return a + b

Python will not check the types by default. Instead, the types can be statically checked before running the program by a tool like mypy:

mypy source.py

Fundamentals

Object:

  • Everything in Python is an object
  • Including integers, strings, lists, functions, classes and class instances

Attributes:

  • An attribute is a value associated with an object
  • Instance Attributes are specific to an instance of a class.
  • Class Attributes are shared among all instances (static variables)
  • Module Attributes are defined at the top level

Syntax

my_list = [1, 2, 3]         # declaring list syntax
my_dict = {'key': 'value'}  # declaring dict syntax

# unpack/unwrap operator
def add(a, b, c):
    return a + b + c
iterables = [1,2,3]
print(add(*iterables)) # same as add(1,2,3)

# list comprehensions
squares = [x**2 for x in range(4)] # = [0,1,4,9]

# slicing
sub_list = squares[1:3]  # = [1,4]

add = lambda x, y: x + y  # lambda functions

name = "Alice" # normal string
greeting = f"Hello, {name}!"  # formatted string (f-string)

Decorators

def my_decorator(func):
    def wrapper():
        print("Decorator start.")
        func()
        print("Decorator end.")
    return wrapper

@my_decorator
def say_hello():
    print("Decorated Function")
say_hello()

Statements

# imports
import math                    # import module
from datetime import datetime  # import specific function/class
import module as alias         # import module with alias
from module import *           # import all names from a module

x  = 5       # assignment
x -= 1       # decrement

# if else
if x > 0:    # conditional
elif x < 0:  # else if condition
else:        # else statement

# loops
for i in range(5):  # for loop
for _ in range(n):  # for loop with unused n
while x > 0:        # while loop
break               # exit loop
continue            # skip to next iteration

def my_function():  # function definition
    return 42       # return value
    pass            # null operation (placeholder)

class MyClass:      # class definition

# exceptions
try:                       # Start of try block
    # ...
except ZeroDivisionError:  # Handle specific exception
    # ...
finally:                   # runs no matter what
    # ...
raise Exception("Err")     # raise exception

with open('file.txt', 'r') as file:  # scoped resource management

global x    # declare global variable
nonlocal y  # declare non-local variable in nested function

assert x == 4  # assert statement

# async
async def my_coroutine():               # define asynchronous function
    await some_async_function()         # await asynchronous call
async with some_async_context_manager:  # async scoped resource manager
    # ...

del x  # Delete a variable or object

# generators
yield value                     # yield value from generator function
yield from another_generator()  # Yield all values from another generator

if __name__ == "__main__":      # check if script is run directly

Built-In Functions

# I/O
print()     # Output data to console
input()     # Reads a line of input from the user.
help()      # Invoke help system
__debug__   # variable set to False if python is run with -O

len()       # Returns length (number of items) of object
type()      # Returns type of object.

# casts
int()       # Convert value to integer
float()     # Convert value to float
str()       # Convert value to string
bool()      # Convert value to boolean

list()      # Create list from an iterable
tuple()     # Create tuple from an iterable
set()       # Create set from an iterable
dict()      # Create associative array

# math
max()       # Return largest item (in iterable)
min()       # Return smallest item (in iterable)
sum()       # Return sum of numbers
abs()       # Return absolute value
round()     # Round number to specified decimal places

# sorting
sorted()    # Returns a new sorted list from the elements of any iterable.
reversed()  # Returns a reversed iterator of a sequence.
enumerate() # Adds a counter to an iterable and returns it as an enumerate object.

zip()       # Combines elements from multiple iterables into tuples.
map()       # Apply function to iterable and return map
filter()    # Construct iterator from elements of an iterable for which a function returns true.
all()       # Return True if all elements of an iterable are true
any()       # Returns True if any element of an iterable is true. If the iterable is empty, returns False.
# special attributes
__doc__         # attribute that stores a docstring
__loader__      # attribute for the module loader object
ule loader object
__name__        # attribute that stores name of module
__package__     # attribute that stores package name of module
__spec__        # attribute that stores module's import specification

# internals
__build_class__ # called internally by class statement
__import__      # called internally by import statement
# async
aiter(iterable) # return asynchronous iterator
anext(iterator) # retrieve
anext(iterator) # retrieve the next item from async iterator

# binary
bin(x)          # convert integer to binary string
hex(x)          # convert integer to hexadecimal string
oct(x)          # convert integer to octal string

breakpoint()    # drop into the debugger at the call site

# math
complex(real, imag) # create complex number
divmod(a, b)        # return quotient and remainder of dividing by b
pow(base, exp)      # return base raised to the power of exp

bytearray()       # create mutable byte array
bytes()           # create immutable bytes object

callable(obj)     # check if object is callable

# interpreter
compile(src, file, mode) # compile source code into code object
eval(expr)               # evaluate python expression from string
exec(object)             # execute python code dynamically
exit()                   # exit interpreter
quit()                   # exit interpreter

# program metadata
copyright()      # display copyright information
credits()        # display credits information
license()        # display license information

# attributes
getattr(obj, name)       # retrieve attribute from object
hasattr(obj, name)       # check if object has specified attribute
delattr(obj, name)       # delete attribute from object
setattr(obj, name, val)  # set attribute on object
property()               # create property attribute

dir(object)      # return list of attributes and methods of object

# data structures
frozenset()      # create immutable set

format(value)    # format value using specified format

hash(object)     # return hash value of object
id(object)       # return the identity of object

# classes
isinstance(object, classinfo) # check if object is instance of class
issubclass(class, classinfo)  # check if class is subclass of another
staticmethod(func)            # transform method into static method
super()                       # return proxy object to access parent class methods
classmethod(func)             # transform method into class method

globals()        # return dict of current global symbol table
locals()         # return dict of current local symbol table

next(iterator)            # retrieve the next item from iterator
memoryview(obj)           # create memory view of object
object()                  # create new featureless object
open(file, mode)          # open file and return file object

# iterables
iter(iterable)            # return iterator for iterable
range(start, stop)        # generate sequence of numbers
slice(start, stop, step)  # create slice object
zip(*iterables)           # combine multiple iterables into tuples

# plaintext
ord(char)        # return the unicode code point for given character
repr(object)     # return string representation of object
ascii(object)    # return printable representation of object
chr(i)           # return character string for unicode code point

vars(object)      # return the __dict__ attribute of object

Code Examples

Generators

A generator is a special type of iterator that allows iteration through a sequence of values. Each time the yield statement of a generator is executed, the function's state is saved, and it can be resumed later.

def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

fib_gen = fibonacci(4) # get generator object

for number in fib_gen: # using the generator
    print(number)

Exceptions

try:
    numerator = 10
    denominator = 0
    result = numerator / denominator
except ZeroDivisionError:
    print("Error: Cannot divide by zero.")
else:
    print("Result:", result)
finally:
    print("Execution completed.") # runs no matter what

Built-in Exceptions:

ArithmeticError
AssertionError
AttributeError
BaseException
BaseExceptionGroup
BlockingIOError
BrokenPipeError
BufferError
BytesWarning
ChildProcessError
ConnectionAbortedError
ConnectionError
ConnectionRefusedError
ConnectionResetError
DeprecationWarning
EOFError
Ellipsis
EncodingWarning
EnvironmentError
Exception
ExceptionGroup
FileExistsError
FileNotFoundError
FloatingPointError
FutureWarning
GeneratorExit
IOError
ImportError
ImportWarning
IndentationError
IndexError
InterruptedError
IsADirectoryError
KeyError
KeyboardInterrupt
LookupError
MemoryError
ModuleNotFoundError
NameError
None
NotADirectoryError
NotImplemented
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
PermissionError
ProcessLookupError
RecursionError
ReferenceError
ResourceWarning
RuntimeError
RuntimeWarning
StopAsyncIteration
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TimeoutError
True
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError