Oregon Curriculum Network
Discovering Math with Python

Five Dimensions of Python

  1. Keywords: basic syntax, reserved terms
  2. Builtins: available on bootup of Python, no import required
  3. Special Names: hooks for tying code to syntax (e.g. obj.attr, obj[index])
  4. Standard Library: "batteries included"
  5. Third Party Packages: vast assortment of libraries, frameworks, distributions


In [1]:
from keyword import kwlist
print(", ".join(kwlist))

False, None, True, and, as, assert, break, class, continue, def, del, elif, else, except, finally, for, from, global, if, import, in, is, lambda, nonlocal, not, or, pass, raise, return, try, while, with, yield


When you boot into a Python shell (REPL), you're not entering a blank canvas or blank slate. Lots of names are already defined, and ready for calling or using.

In [2]:
exceptions, callables, not_callables = [], [], []
for name in dir(__builtins__):     # cycle through a bunch of strings
    obj = eval(name)               # turn strings back into objects
    if type(obj) == type and issubclass(obj, BaseException):
        exceptions.append(name)    # types of exception
    elif callable(obj):       
        callables.append(name)     # callable 
        not_callables.append(name) # whatever is left over
print("Exceptions\n", exceptions)
print("Callables\n", callables)
print("Other\n", not_callables)

 ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'EnvironmentError', 'Exception', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'NotADirectoryError', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError']
 ['__build_class__', '__import__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'dreload', 'enumerate', 'eval', 'exec', 'filter', 'float', 'format', 'frozenset', 'get_ipython', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
 ['Ellipsis', 'False', 'None', 'NotImplemented', 'True', '__IPYTHON__', '__debug__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

Special Names

Special names all have a similar look: __name__

In other words: two underlines, a name, two underlines. I sometimes think of the special names as the Python's __ribs__ (snakes have lots of ribs).

You don't make up or define these special names yourself. They come with the language. Newer versions of Python may have more of them, but within a given version, they're fixed.

Think of special names as like the strings a puppeteer uses to control marrionettes. Each string goes to a specific aspect of Python's grammar, such as calling an object, getting or setting an object's attribute, getting or setting using index notation (square brackets).

Many object types come with predefined behaviors for any or all of the above. When you write your own classes, or subclass an existing type, that's when you have the ability to define or override some special name behavior.

In [3]:
This type of object gets along with nobody!

adjective North American informal
adjective: ornery

    bad-tempered and combative.
    "some hogs are just mean and ornery"
    synonyms:	grouchy, grumpy, cranky, crotchety, cantankerous, bad-tempered, 
    ill-tempered, dyspeptic, irascible, waspish
自 = self in Chinese (showing that self is not a keyword, just a placeholder)

class Ornery:
  def __init__(, name="Fred"):
    .name = name
    print("A sourpuss is born!")
  def __getitem__(, key):
    return "How dare you touch me with those brackets!"
  def __call__(, *args, **kwargs):
    return "Don't call me at home!"
  def __getattr__(, attr):
    return "I'm insulted you'd suppose I'd have {}".format(attr)
  def __repr__():
    return "Don't bother me!  Go away."
  def __invert__():
    return "I can't invert, are you kidding?"

grumpy = Ornery()
print(grumpy("Hello?"))  # __call__
print(grumpy.mood)       # __getattr__
print(grumpy[3])         # __getitem__
print(~grumpy)           # __invert__
print(grumpy)            # __repr__

A sourpuss is born!
Don't call me at home!
I'm insulted you'd suppose I'd have mood
How dare you touch me with those brackets!
I can't invert, are you kidding?
Don't bother me!  Go away.

Standard Library

Lets take a tour.

Third Party

Lets visit PiPy