Python

Introduction

Interpreted programming language, especially popular in machine learning applications.

For a quick reference see here.

Types

Primitive types are Integers, Float, String, Boolean.

Non-primitive data structures are List, Tuple, Dictionary, Set. Time complexity for these are posted here.

These (alongside any other data type) can be used with type signatures, for example:

from typing import Dict, List

def foo(x: int | Dict[int, int | float],
        y: float | None)

Where the a | b (or nested variants) signify that the type could be either a or b.

Standard library

Strings

Math

Random

File management

Package Management

  • pipreqs is more robust than pip freeze to generate requirements.txt files.

Object-oriented programming

Functional programming

Libraries

  • JAX
  • PyTorch
  • pytest
  • matplotlib

Debugging

  • (Andrej Karpathy) import code; code.interact(local=locals()) is the sweet spot in between print() and import pdb; pdb.trace().
  • See also IPython.embed which does the same but comes with all the benefits of IPython.

Tips

Formatted Printing

name = "Nazaal"
test = f"Name {name}"
print(test)

Resources

Anki

Give an example of using composition over inheritance.

Personal communication, Ti.

Suppose we have the following class whose functionality we want to use in other classes without reimplemeting it.

class Stateful:
    def init(self, key):
        self._key_state = key

    def _next_key(self):
        self._key_state, new_key = jax.random.split(self._key_state)
        return new_key

And we have another class Environment where we want to make use of state via the Stateful class above.

The inheritance approach is:

@dataclass
class Environment(Stateful):
    seed: int

    def __post_init__(self):
        self.init(jax.random.PRNGKey(self.seed))

    def foo(self, bar):
        key = self._next_key()
        ...

The composition approach is:

@dataclass
class Environment:
    seed: int
    state: Stateful
    ...

    def __post_init__(self):
        self.state = Stateful(self.seed)

    def foo(self, bar):
        key = self.state._next_key()
        ...

When using dataclasses, you can make them slotted so that new attributes cannot be inserted with the dot syntax.

What is the difference between @property from the Protocol class and @abstractmethod from the ABC class?

Protocol classes do not necessarily need to be inherited from for them to be used and can be seen as an interface class, meanwhile ABC requires inheritance. In that sense, using Protocol is more flexible, since any object which implements the methods defined inside it, even from third party packages. Meanwhile, any class Foo which inherits from an abstract base class Bar(ABC) must implement all @abstractmethod's defined.

Emacs 29.4 (Org mode 9.6.15)