Skip to content

Instantly share code, notes, and snippets.

@datavudeja
Forked from mjdecker/basics.py
Created November 26, 2025 17:31
Show Gist options
  • Select an option

  • Save datavudeja/b812e536b2e50a5e8894a36d40c6ef4b to your computer and use it in GitHub Desktop.

Select an option

Save datavudeja/b812e536b2e50a5e8894a36d40c6ef4b to your computer and use it in GitHub Desktop.
Python language examples with notes
# General Information
# * High-level programming language
# * General-purpose (vs. domain specific)
# * Created by Guido van Rossum (1991)
# * Emphasizes:
# * Code readability
# * Highly-expressive syntax
#
#
# Some specifics
# * Intepreted
# * Dynamically typed (with duck typing)
# * Strongly typed
# * Paradigms (includes)
# * imperative
# * procedural
# * object-oriented
# * functional
# * Whitespace is significant (no blocks, i.e, {} )
#
# Website: https://www.python.org
#
# Downloads: # * https://www.python.org/downloads/
# * Python 3 (similar, but not compatible with Python 2)
# * Windows - Use installer
# * set path=%path%;C:\python36
# * Mac - should use Homebrew, or website
# * Unix - package manager, or website
# * export PATH="PYTHON_INSTALL_DIRECTORY:$PATH"
# * Never put '.' (current directory) in path.
#
#
# Language Info: https://docs.python.org/3/
# or just google
#
# Tutorial: https://docs.python.org/3/tutorial/appetite.html
# * Show, line where it is named afer Monty python
# * For fun, http://legacy.python.org/search/hypermail/python-1994q2/0003.html
#
# also this
import antigravity
#
# python3
# * read–eval–print loop (REPL)
# python3 program.py [args] (how to access in program at later date)
# * Execute python program
#
# Unix
# * At top of file, '#!/usr/local/bin/python3' and make file executable (UNIX "shebang" line)
# Python Tool doc - (https://docs.python.org/3/using/cmdline.html#using-on-general)
# * Or, man python3 (unix)
#
# Interactive Mode:
# * >>> usually primary prompt
# * ... secondary prommpt (e.g., multiple line constructs)
# * nothing is output
# * Unix ^ + D, Windows ^ + Z, exit(), or quit()
# * ^ is control
#
# Python Encoding
# * Put '# -*- coding: [encoding] -*-' as first line of a file
# * May occur after shebang line
# In REPL:
# What... is the airspeed of an unladen swallow?
airspeed_velocity = 11 # What do you mean? An African or European swallow?
# Huh? I... I don't know that. Auuuuuuuugh.
text = "# Three above are comments, This is not as it's inside quotes."
# Python as a simple calculator
2 + 2
# Order of ops: https://docs.python.org/3/reference/expressions.html#operator-precedence
42 - 5 * 6
# Typical force precedence (4.0 - to set up next one)
(42 - 5 * 6) / 4.0
# What do you think we get, nope, a float (differs from Python2)
8 / 5
# Now, an int (floor function)
8 // 5
# Python 3: has only one integer number and floating-point number type (long in python 2, but python 3 but unlimited precision/size) and float (usually a double)
# modulus
8 % 5
# powers
2 ** 10
# as this is a programming language that can change state we have assignment
# An identifier can is [:alpha:_][:alphanum:_]* unlimited length and case significant.
# Python 3 adds unicode
Δ = 4 - 3
# what type of type systems is this, again?
base = 10
power = 3
# if do not remember precedence use ()
base ** power * 9 + 1
# Can mix int and float types (What do you think about this: strong or weak typing?)
32 * .25 - 1
# In REPL, result of last printed expression is held in _
tax = 6.75 / 100 # variable has what type now?
price = 8 + 12 # variable has what type now?
price * tax
price + _
round(_, 2)
# treat _ as read-only, as creates a new variable hiding built-in variable with its magic behavior (Python's words BTW)
_ = 42
7 * 3
_
# Python additionally suport: complex numbers, Decimal, and Fraction
# python namespace is a mapping from names to objects
# E.g.,builtin namespace (interpretter startup), global namespace (created when read in), function local namespace (on call)
# declarations in a namespace are attributes (. operator)
import sys
# behaves as object
print(sys)
sys.stderr
# Based off of C++ and Modula-3
# Allows: inheritance, multiple base classes, override methods, call base class methods
# like functions must be executed (encountered before use)
class bird :
pass
# class definitions create a new namespace and local scope
# Like function, and othe things in python classes are objects
print(bird)
# Classes can be modified at runtime
# All normal members are public and all methods virtual
# builtins can be base class
# operators can be overloaded
# objects are aliased when assigned (or passed, another way to think about the pass by object-reference)
larry = bird
print(larry)
# A simple class
class bird :
"""A bird class"""
type = 'Swallow'
def velocity() :
return 11
# calling object (instantiation)
swallow = bird()
print(bird.type)
print(bird.velocity())
# constructor
class bird :
# first argument is always the object (like this in C++)
# self is convention (some editors (like Sublime)) rely on it
# strongly urge following this convention
def __init__(self, type, airspeed = 11) :
# added at runtime
self.type = type
self.airspeed = airspeed
def velocity(self) :
return self.airspeed
# Class instances (not classes themselves) have two type of attributes: data and methods
# data (data members)
european = bird('European Swallow')
print(european.type)
european.carrying_coconut = True
print(european.carrying_coconut)
del european.carrying_coconut
# never happened
# methods
print(bird.velocity)
print(european.velocity)
assert bird.velocity(european) == european.velocity()
# a method object is created on reference
european_velocity = european.velocity
print(european_velocity)
print(european_velocity())
# methods have some attributes
print(european_velocity.__self__)
print(european_velocity.__func__)
class cat :
# class variable (shared)
kind = 'feline'
# incorect usage of variable
tricks = []
def __init__(self, name) :
# instance variable
self.name = name
def add_trick(self, trick) :
self.tricks.append(trick)
# ask for cat names
c = cat('Shampoo')
d = cat('Spot')
c.add_trick('sleep')
d.add_trick('scratch')
print(c.tricks)
# Remarks
# data attributes override method attributes with same name
# Python does not support data hiding (convention does)
# Class functions need not be declared in a class
# Inheritence (Base name may be module.classname)
# Scoping: If attribute not resolved in class, searches base class (applied recursively)
class european(bird) :
def __init__(self) :
self.type = 'European Swallow'
self.airspeed = 11
class african(bird) :
load_factor = 2
def __init__(self, number_coconuts) :
self.type = 'African Swallow'
self.airspeed = 42
self.number_coconuts = number_coconuts
def velocity(self) :
#return self.airspeed - self.number_coconuts * african.load_factor
#return bird.velocity(self) - self.number_coconuts * african.load_factor
return super().velocity() - self.number_coconuts * african.load_factor
def print_bird(birdie) :
print('type:', birdie.type, 'velocity:', birdie.velocity())
# is this polymorhpism?
e = european()
print_bird(e)
a = african(1)
print_bird(a)
# builtin inheritence functions (may also have tuple of types)
print(isinstance(e, bird))
print(isinstance(e, european))
print(isinstance(e, (bird, european)))
print(isinstance(e, african))
print(isinstance(e, (bird, african)))
print(issubclass(bool, int))
print(issubclass(bool, bird))
# multiple inheritence
# attributes inherited from a parent class as depth-first, left-to-right, not searching twice in the same class where there is an overlap in the hierarchy
# all inherit indirectly from object if not specified
class norwegian_blue(bird, object) :
pass
# no private, but leading underscore is convention for private
# if two leading underscore and at most one trailing name will be name mangled (avoid collision in super/sub classes)
# https://en.wikipedia.org/wiki/Name_mangling#Python
# Special methods (e.g., operator overloading)
# https://docs.python.org/3/reference/datamodel.html
# Operator overloading alone is why Python > Java
class point :
def __init__(self, x, y) :
self.x = x
self.y = y
def __add__(self, other) :
return point(self.x + other.x, self.y + other.y)
# try with and without __str__
def __str__(self) :
return str((self.x, self.y))
point_one = point(1,2)
point_two = point(3,4)
print(point_one + point_two)
# Coroutines is a more general generator (specify courouting to jump to)
# https://en.wikipedia.org/wiki/Coroutine
# Similar to mutual recursion with tail recursion (no new stack frame), but more flexible/effidient
# (do not restart (resume), yield instead of return (which has to be in tail),
# hold state)
# Reuse circular queue
class circular_queue :
def __init__(self, max_size = 128) :
self.max_size = max_size
self.queue = [None] * self.max_size
self.size = 0
self.start = 0
self.end = -1
def enqueue(self, item) :
assert not self.is_full()
self.size += 1
self.end = (self.end + 1) % self.max_size
self.queue[self.end] = item
def dequeue(self) :
assert not self.is_empty()
item = self.front()
self.size -= 1
self.start = (self.start + 1) % self.max_size
return item
def front(self) :
assert not self.is_empty()
return self.queue[self.start]
def back(self) :
assert not self.is_empty()
return self.queue[self.end]
def is_full(self) :
return self.size == self.max_size
def is_empty(self) :
return self.size == 0
def __str__(self) :
return 'size: {0} queue: {1}'.format(self.size, str(self.queue))
def __iter__(self) :
return circular_queue_iterator(self)
def generate(self) :
for i in range(self.size) :
yield self.queue[(self.start + i) % self.max_size]
done = False
queue = circular_queue(4)
def produce() :
print('Enter produce')
while not done :
while not queue.is_full() :
queue.enqueue(input('Item: '))
yield consume
print('Exit produce')
def consume() :
print('Enter consume')
while not done :
while not queue.is_empty() :
print(queue.dequeue(), end = ', ')
print()
yield produce
count = 5
routines = { produce: produce(), consume: consume() }
current = produce
while not done :
count -= 1
if count == 0 : done = True
try :
current = next(routines[current])
except StopIteration :
pass
# To use with-statement, define __enter__ and __exit__
class resource :
def __init__(self, filename) :
print('Constructor')
self.file = open(filename, 'r')
def __enter__(self) :
print('enter')
return self
# if no exception was raised, arguments are None
def __exit__(self, exc_type, exc_value, traceback) :
print('Exit')
# True, means do not propagate exception
return True
obj = resource('dijkstra.txt')
print('pre with-statement')
with obj as rsrc :
print('with-statement')
# What are the basic operations of a stack
# top, push, pop
stack = []
stack.append(1)
stack.append(2)
stack.append(3)
print(stack)
tos = stack[-1]
print(tos)
tos = stack.pop()
print(tos)
print(stack)
# What type of structure is stack
# LIFO
# How do you categorize a queue
# FIFO (techically, stack is a LIFO queue)
# What are the operations of a queue?
# enqueue(), first(), dequeue()
# So, list is not effifcient for a queue so will use a deque
from collections import deque
queue = deque()
queue.append(1)
queue.append(2)
queue.append(3)
print(queue)
first = queue[0]
print(first)
first = queue.popleft()
print(first)
print(queue)
# So, how might you go about generating a list of the 20 powers of 2 (up to 2 ** 20)
powers = []
for i in range(21) :
powers.append(2 ** i)
print(powers)
# Python has more power syntax for generating lists
# First is we could use maps and lambdas
# These have roots in functional languages
# A llambda is an anyonymous (or unamed function). The syntax is:
#lambda param: expression
# We can assign them to variables and parameters, and call them
func = lambda i: 2 ** i
func(3)
# map takes a list and applies a function to each element in an iterable sequence and returns a list
values = [1, 2, 3]
powers = map(func, values)
print(values)
# actually a map object, use function style cast
print(powers)
print(list(powers))
# Lets combine this syntax
powers = list(map(lambda i: 2 ** i, range(21)))
# Python has an even more power syntax called list-comprehensions
# The form is
#[expression for identifier in sequence]
powers = [2 ** i for i in range(21)]
print(powers)
# How might we use this to generate a list of first 10 cubes?
cubes = [i ** 3 for i in range(10)]
print(cubes)
# The actual syntax is a bit longer
# you can have additional for and if clauses
# For example, cartesian product (as tuples)
product = [(x, y) for x in [1, 2, 3] for y in [3, 2, 1]]
print(product)
# So, if come into play when you want to place restrictions
# such as don't want when x == y
product = [(x, y) for x in [1, 2, 3] for y in [3, 2, 1] if x != y]
print(product)
# order is important (symbol does not exist) or different order of tuples
#product = [(x, y) for x in [1, 2, 3] if x != y for y in [3, 2, 1]]
#print(product)
# Compare this to the actual loop version (and how much more expressive Python is here)
product = []
for x in [1, 2, 3] :
for y in [3, 2, 1] :
if x != y :
product.append((x, y))
print(product)
# list comprehensions can be nested (its the expression of another list comprehension)
# Lets take a matrix (2-dimentional array)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# The transpose of this is (flip rows/columns):
transpose = [
[1, 4, 7],
[2, 5, 8],
[3, 6, 9]
]
# With a list comprehension
# first lest iterate over every row
transpose = [row for row in matrix]
print(transpose)
# This may be a bit difficult, but
# now we got every row and we want to generate the transpose
# So, for transpose we need the first position from each row
# second, we need second position, etc.
# What does that sound like?
# For value 0 (outer), we go through each row of matrix and generate a new row (inner)
# Continue for 1, and 2
transpose = [[row[i] for row in matrix] for i in range(3)]
print(transpose)
# This is some hard to wrap your head around stuff, but
# can you help me try and square all elements in an matrix?
# So, we are generating a 2-D array (so, nested list comprehension)
square = [[element ** 2 for element in row] for row in matrix]
# del - deletes items from list and variables
a = 42
print(a)
del a
#print(a)
# How do you delete an element in an array
data = [1, 2, 3]
data[1:2] = []
print(data)
# can also use del
data = [1, 2, 3]
del data[1]
print(data)
# can also be used for more sequence types
# Tuple packing and unpacking
# Extension to what we saw earlier
# pack
tuple = 0, 1
print(tuple)
# unpack
prev, current = tuple
print(prev, current)
# tuples also support indexing
print(tuple[1])
# dictionaries
# empty dictionary
birthday_dict = {}
# key value pairs, key index to value
# This is also the mechanism for insert
birthday_dict['Decker'] = 'September 7th'
birthday_dict['Reese'] = 'February 15th'
birthday_dict['Decker']
# How do we create dictionaries?
dictionary = {'key': 'value'}
print(dictionary)
#or
dictionary = dict([('key', 'value')])
print(dictionary)
birthday_dict = { 'Decker': 'September 7th', 'Reese': 'February 15th'}
print(birthday_dict)
# if key are strings, can
dictionary = dict(jack=4139, jill=4127, hill=4098)
print(dictionary)
# update a dictionary with another dictionary (overwrite existing)
birthday_dict.update({'Decker': 'October 8th', 'Picard': 'July 13th'})
# may also be an iterable object of tuples E.g.,
# [('Decker', 'October 8th'), ('Picard', 'July 13th')]
print(birthday_dict)
# You can bind multiple values in for
for index, value in enumerate(['eeny', 'mini', 'miny', 'moe']) :
print(index, value)
# Dict looping
questions = {'name': 'lancelot', 'quest': 'the holy grail', 'favorite color': 'blue'}
for key, value in questions.items() :
# format a string
'What is your {0}? It is {1}.'.format(key, value)
print('What is your {0}? It is {1}.'.format(key, value))
# So, if you drop the ':' syntax, you get a set
# basically a dictionary where the key is also the value
a_set = {'item'}
print(a_set)
# sets do not allow duplicates
set_one = set('kadabra')
print(set_one)
set_two = set('alakazam')
print(set_two)
# What operations are there on a set : union, intersection, difference
# difference
print(set_one - set_two)
# intersection
print(set_one & set_two)
# union
print(set_one | set_two)
# symmetric difference
print((set_one - set_two) | (set_two - set_one)) # and other ways
print(set_one ^ set_two)
# set and dictionary comprehensions also exist and use {}
a_set = {x for x in 'kadabra' if x not in 'abk'}
print(a_set)
# Sequences (same type) can be compared (lexographically (iterative apply comparison to elements))
print([1, 2, 3] == [1, 2, 3])
print([1, 2, 3] < [1, 2, 4])
done = False
while not done :
try :
x = int(input('Enter a number: '))
# skipped on exception
done = True
# if exception matches
#except ValueError:
# if not correct exception type (decendent of Exception class)
#except str :
#except ArithmeticError :
# You can have multiple values in an except
#except (ValueError, ArithmeticError) :
# except everything (must be last)
except :
print('Not a number. Please, try again.')
# reraise
raise
# except ValueError:
# pass
# You can also have multiple except
class error(Exception):
pass
class fatal(error) :
pass
class warning(error):
pass
# a list of types!!!
for aclass in [error, fatal, warning] :
try :
# raise exception
raise aclass()
# first matching is executed (put error first) and try
# except error :
# print('An error occurred')
# except fatal :
# print('A fatal error occurred')
# except warning :
# print('A warning occurred')
except fatal :
print('A fatal error occurred')
except warning :
print('A warning occurred')
except error :
print('An error occurred')
import sys
for arg in sys.argv[1:] :
try :
file = open(arg, 'r')
except OSError :
print('cannot open', arg)
# on success of all of try (must be after all except)
else :
print(arg, ':', len(file.readlines()), 'lines')
file.close()
# Instance variable can be accessed
try :
# cause exception to occur (instance (default ctor) or class)
raise Exception('one fish', 'two fish', 'red fish', 'blue fish')
except Exception as exception:
print(type(exception))
# the args as tuple
print(exception.args)
# via __str__
print(exception)
cat, i_n, the, hat = exception.args
print('arg1:', cat, 'arg2', i_n, 'arg3:', the, 'arg4:',hat)
# args are printed when unhandled
#raise
# finally is always run (cleanup), Java has this too
def divide(x, y):
try:
result = x / y
return result
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("executing finally clause")
divide(0, 1)
print()
divide(1, 0)
print()
# runs finally before breaks (finally very useful for files/network connections)
divide('2', '1')
# for-statements
# What forms of for statements you have in C++?
# for(int i = 0; i < 10; ++i); and for(int i : array);
# Python's for is like the range-based for it iterates over items in a sequence (in order)
animals = ['cat', 'dog', 'fish', 'echidna']
for animal in animals :
print(animal, len(animal))
# What if you modify the list in the loop
animals = ['cat', 'dog', 'fish', 'echidna']
for animal in animals :
animals.insert(0, animals[3])
print(animals)
# Can iterate over a copy
animals = ['cat', 'dog', 'fish', 'echidna']
for animal in animals[:] :
animals.insert(0, animals[3])
print(animals)
# But what if you need a sequence of numbers?
# Never, fear the range is here?
for i in range(5) :
# sequence 0, 1, 2, 3, 4 (think mimic i < 5)
# stop is never included
print(i, end=' ')
# range(stop)
# range(start, stop[, step])
for i in range(5, 10) : print(i, end=' ')
for i in range(0, 10, 3) : print(i, end=' ')
for i in range(-10, -100, -30) : print(i, end=' ')
# Given what you know of lists/strings and range,
# How do you iterate over the indices of this list to print (index, vegetable)?
vegetables = ['carrot', 'radish', 'napa cabbage']
for index in range(len(vegetables)) :
print(index, vegetables[index])
# see a bit more why end point not included in range?
# Could also use enumerate, but we have not done tuples, yet
# Some scoping we will talk more later
# What in C++ is in an not in scope, Python?
for i in range(5) :
# sequence 0, 1, 2, 3, 4 (think mimic i < 5)
print(i, end=' ')
print(i)
integer = 0
while integer < 10 :
integer += 1
sum = integer
print(integer, sum)
# https://docs.python.org/3/library/stdtypes.html#range
# Actually, an immutable sequence type (object) that returns the successive items
# when you iterate over it. No, list need generated.
print(range(10))
# However, can be converted to a list with function style cast
# Like most types in Python
list(range(10))
# There are more iterable items in Python for the various types
# break, continue, and loop-else?
# First, break
# lets search for what is divisible by what
for n in range(2, 10) :
for x in range(2, n) :
if n % x == 0 :
print(n, 'equals', x, '*', n//x)
break
# What if we want to know if it is a prime, what might we do?
# Various answers, another loop, extend n to plus 1, and check if reach
# Now something you have never seen
for n in range(2, 10) :
for x in range(2, n) :
if n % x == 0 :
print(n, 'equals', x, '*', n//x)
break
# eyes are not decieving you (the else goes with the for)
else :
# loop fell through without finding a factor (executed if list exhausted)
print(n, 'is a prime number')
# While also has an else which executes when it is False
# Actually, both are sort of when false
i = 0
while i < 21 :
print("2 ** ", i, ' = ', 2 ** i)
i += 1
else :
print ("21 = blackjack")
# continue is also supported
occupations = ['policeman', 'scientist', 'waldo', 'president']
for occupation in occupations :
# guard clause - a precondition check to protet and simplify main execution branch
# deviation of structured programming
if occupation != 'waldo' :
continue
print('Found Waldo!!!')
# A function is born when you use the def reserved word
def hello() :
print('Hello')
# function needs declared before it is called at runtime
hello()
n = 0
def foo():
print('foo')
# Won't work
#n += 1
globals()['n'] += 1
if n < 3 :
bar()
def bar():
print('bar')
foo()
foo()
# This redefines the function with a parameter
def hello(name) :
print('Hello', name)
# old function is gone
#hello()
hello('Michael')
# The execution of a function introduces a new symbol table
# used for the local variables of the function. More precisely,
# all variable assignments in a function store the value in the
# local symbol table; whereas variable references first look in
# the local symbol table, then in the local symbol tables of enclosing
# functions, then in the global symbol table, and finally in the table
# of built-in names. Thus, global variables cannot be directly assigned
# a value within a function (unless named in a global statement),
# although they may be referenced.
# The actual parameters (arguments) to a function call are
# introduced in the local symbol table of the called function
# when it is called; thus, arguments are passed using call by value
# (where the value is always an *object reference*, not the value
# of the object). When a function calls another function, a new
# local symbol table is created for that call.
def fibonacci(max_num) :
"""Print Fibonacci numbers up to max_num""" # docstring
prev, current = 0, 1
while prev < max_num :
print(prev, end=' ')
prev, current = current, prev + current
print()
fibonacci(2000)
# function definition introduces a new name
print(fibonacci)
print(fibonacci.__doc__)
# Python supports aliasing
fibo = fibonacci
fibo(2000)
def fibonacci_list(max_num) :
"""Returns an array with the Fibonacci numbers up to max_num"""
prev, current = 0, 1
fibo_list = []
while prev < max_num :
fibo_list.append(prev)
prev, current = current, prev + current
return fibo_list
print(fibonacci_list(2000))
# All functions actually return something
print(fibonacci(2000))
# multiple return
def next_fibo(prev, current) :
return current, prev + current
a = next_fibo(0, 1)
# a is what is called a tuple (math def = finite ordered list (sequence))
# basically an immutable list
print(a)
# can be unpacked
a, b = next_fibo(0, 1)
# Parameters
# Default parameters
def guessing_game(values, answer_pos = 0, tries_param=3) :
if answer_pos < 0 or answer_pos >= len(values) :
print('Invalid answer position')
return
tries = tries_param
for atry in range(tries) :
print(tries, 'tries remaining')
# Can cast to string
guess = input('Guess from one of the following: ' + str(values) + ' ')
# in tests membership
if guess not in values :
print('Invalid guess')
elif values[answer_pos] == guess :
print('Good, good, but you are not a Jedi, yet')
break
tries -= 1
else :
print('You failed')
# ask students for participation on values
#guessing_game(['a', 'b', 'c'])
# one or both default params can be specified
#guessing_game(['a', 'b', 'c'], 2)
#guessing_game(['a', 'b', 'c'], 2, 5)
# default values are evaluated at defining scope
i = 5
def i_func(val=i):
print(i)
i = 42
i_func()
# WARNING WARNING WARNING
# default parameters are assigned to only once
# It is good practice (any language) to not modify parameters used only for reading
def list_append(value, alist = []) :
alist.append(value)
return alist
print(list_append(0))
print(list_append(1))
print(list_append(2))
# Keyword arguments
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")
parrot(1000) # 1 positional argument
parrot(voltage=1000) # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump') # 3 positional arguments
parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword
# parrot() # required argument missing
# parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument
# parrot(110, voltage=220) # duplicate value for the same argument
# parrot(actor='John Cleese') # unknown keyword argument
# keyword arguments must exist and follow positional, but order of keyword do not matter
# No argument can be assigned to twice
# keyword arguments can also appear after *name
def donut_shop(kind, *arguments, **keywords) :
print('Do you have any', kind, 'donuts?')
print('Naaah, we are out of', kind, 'donuts.')
# additional positional populate *name
for argument in arguments :
print(argument)
# additional keyword populate **name
for keyword in keywords :
print(keyword, ':', keywords[keyword])
# order of both is maintained
donut_shop('glazed',
'Well, in that case. In that case. What do you have?',
'All I\'ve got right now is this box of one dozen starving crazed weasels.',
artist='Wierd Al',
song='Albuquerque')
# unpacking
params = [3, 6]
range(*params)
params = {'voltage': 'four million', 'state': 'bleedin\' demised', 'action': 'VOOM'}
parrot(**params)
# Show them annotations: https://docs.python.org/3/tutorial/controlflow.html#defining-functions
# Have them read 4.7.6. Documentation Strings and 4.8: https://docs.python.org/3/tutorial/controlflow.html#defining-functions
# if-statement
# What do you think an if is like in Python?
num = 0
if num < 0 :
print('negative')
# Of course we have an else
num = 0
if num < 0 :
print('negative')
else :
print('non-negative')
# What about nested chains?
# num = 0
# if num < 0 :
# print('negative')
# else if num == 0 : # not valid
# print('zero')
# else :
# print('positive')
num = 0
if num < 0 :
print('negative')
elif num == 0 :
print('zero')
else :
print('positive')
# You can have multiple elif (substitute for switch/case)
num = 2
if num < 0 :
print('negative')
elif num == 0 :
print('zero')
elif num == 1 :
print('one')
else :
print('more')
# To make things easier lets mess with input: try with 1 and foo
num = input('Please input an integer: ')
# A bit disceptive, its a string (no ending newline)
print(num)
num
# need to convert to int, has function style casting: try with 1 and foo
num = int(input('Please input an integer: '))
# There are occasions when input from terminal is usefull (password), however, generally want process automated
# str vs repr
lyric = "If you don't eat your meat, you can't have any pudding!"
# human readable
print(str(lyric))
# interpreter readable
print(repr(lyric))
# format via string.format
import math
print('PI: {0:.5f}, Gravity: {1:2d} ft/sec'.format(math.pi, 32))
# There are a course a lot more ways to use format...
# file io
# could not be much easier...
# file = open(filename, mode)
# r is read, w is write, r+ is rw, b is byte, a is append
file = open('dijkstra.txt', 'r')
quote = file.read()
#quote = file.read(size)
#quote = file.readline()
#liens = file.read().splitlines()
# if you open, you must close
file.close()
print(quote)
infile = open('dijkstra.txt', 'r')
outfile = open('stripped.txt', 'w')
for line in infile:
#print(line)
outfile.write(line.strip())
infile.close()
outfile.close()
# look at file output
# with-statement -auto closes
with open('dijkstra.txt') as dijkstra_file :
data = dijkstra_file.read()
print(dijkstra_file.closed)
# Python also support json input/output, and my favorite pickle: https://docs.python.org/3/library/pickle.html#module-pickle
# So what do you think a list is:
# an array
fibonacci = [0, 1, 1, 2, 3]
fibonacci
# lists are another sequence type like strings and
fibonacci[0]
fibonacci[-1]
fibonacci[-3:]
# Tell me about C++ arrays, such as what restrictions?
# They are homogeneous...
# Python are not restricted to same element, but often are...
record = ['Super Smash Bros. Ultimate', 'Bandai Namco Studios', 2018]
record[0]
record[1]
record[2]
# concatenation is supported
fibonacci + [5, 8, 13, 21, 34]
# original is unmodified
fibonacci
# Multiplication is supported
doubled = fibonacci * 2
fibonacci
doubled
# So, strings are immutable, what about lists?
cubes = [1, 8, 27, 65, 125]
# 65 is not right
4 ** 3
# fix
cubes[3] = 64
cubes
# Well, concatenation creates a new list, which can be very inefficient, appending?
cubes.append(216)
cubes.append(7 ** 3)
cubes
# But, I have a list I need added...
fibonacci.extend([5, 8, 13, 21, 34])
fibonacci
# Need to remove elements at the end?
# Remove last (and return)
fibonacci.pop()
# Remove element at position 2
fibonacci.pop(2)
# lists directly support stack
stack = []
stack.append(42)
stack.append(3);
stack[-1]
stack.pop()
# Modification with slices?
grades = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
grades
# replace
grades[2:5] = ['C', 'D', 'E']
grades
# They need not be the same size
grades[3:7] = ['d', 'f']
grades
# or erase
grades[1:4] = []
grades
# lists are not copied on assignment
original = [1, 2, 3]
copy = original
copy[2] = 5
original
# new list
copy = [3, 2, 1]
copy
original
# shallow copy (lists are but not contents)
copy_fib = fibonacci[:]
copy_fib[0] = 42;
fibonacci
copy_fib
# Like string, len gives the length
len(grades)
# Lists can contain lists
song_one = ['Jonathan Coulton', 'Code Monkey', 2006]
song_two = ['Basshunter', 'DotA']
songs = [song_one, song_two]
songs
# A module is a file containing Python definitions statements
# The name is the file minus the .py
import function
# first the set of built-in modules is searched then variables in sys.path are searched
# you can also modify at runtime
import sys
print(sys.path)
# definitions are namespaced with the module name
print(function.binary_search([1, 2, 3, 4], 3, 0))
# you can ask the module's name
print(function.__name__)
# Remember you can alias in Python
#binary_search = function.binary_search
#print(binary_search([1, 2, 3, 4], 3, 0))
# You can also directly import a name
from function import binary_search
from function import insertion_sort, split_char
print(binary_search([1, 2, 3, 4], 3, 0))
# can also important anything not beginning with _
# not recommended same as using namespace std;
from function import *
# When you run a program from the command line it gets the __main__ namespace
print(__name__)
# you can use this to run statements when run (and not imported)
if __name__ == "__main__" :
# do main processing
import sys
# process command line
print(sys.argv[0])
# Compiled Python - __pycache__/module.version.pyc
# Packages
# show package directory
#import package
#import package.submodule
# Use __all__ to for * syntax
# bar still not initialized
from package import *
# What are the python scopes again?
# innermost (local) scope, enclosing functions, globals, built-ins
# scoped are static, but name resolution is dynamic (this is possibly changing)
# assignment and del add and remove bindings (that word again) and go to local scope
# import and function decl bind names in local scope
# Scoping example
def python_scope() :
def local_scope() :
scam = 'local scam'
def nonlocal_scope() :
# non local will continue up functions until first found variable
nonlocal scam
scam = "nonlocal scam"
def global_scope() :
# no previous binding
global scam
scam = 'global scam'
scam = 'python scam'
print('local scope:', scam)
local_scope()
print('local assignment:', scam)
nonlocal_scope()
print('nonlocal assignment:', scam)
global_scope()
print('global assignment:', scam)
python_scope()
print('global scope:', scam)
# What type do you thing this is?
"butterscotch"
# How about this one?
'a'
# Both are strings
'butterscotch'
# Just as in C++, \ can be used to escape characters
'\'escaped\''
# Or use the other type of quote
"'no need to escape these'"
'"or these"'
# print, how real output is done, Python 2 requires no parenthesis (might be why people still use 2)
'"It\'s just a flesh wound." Black Knight'
print('"It\'s just a flesh wound." Black Knight')
# How do you think you print a '\'?
# escape
print('C:\\WINDOWS\\system32')
# raw strings
print(r'C:\WINDOWS\system32')
# What you always wanted, multi-line quotes.
"""This was a triump
I'm making a note here
HUGE SUCCESS
"""
# Can use either quote, no need to escape
'''It's hard to overstate
my satisfaction
Aperture Science
'''
# If you want to suppress new line being appended use \ (line continuation character?)
'''\
program arg [optional_arg]
* arg - an argument
* optional_arg - an optional argument\
'''
# concatenation
"Fat Man" + " and " + "Little Boy"
# string multiplication
"ha" * 3 + " " + "ha" * 7
# string next to each other are concatenated automatically
'Muffin ' 'Button'
# to break into long lines use parenthesis
# What type is this?
text = ('Your mother was a hamster and '
'your father smelt of elderberries!')
text
# must both be literals, not variables or expressions
prefix = 'Py'
#prefix 'thon'
#('un' * 3) 'ium'
prefix + 'thon'
# [] operator supported (well, arrays in general support these ops)
bird = 'word'
bird[0] # 0-position offset
bird[3]
bird[3][0] # these are strings of size 1
# bird[4] - errors
# negative numbers?
bird[-1] # negative offset cause -0 == 0
bird[-4]
# bird[-5] - error
# slicing in this case substring, but applies to other lists
word = 'Python'
word[0:2] # left included, right excluded [0,2)
word[2:5] # length is 5 - 2 == 3
# empty sides expand to remaining part of list (front or back)
word[:2]
word[2:]
# note, the indexing is on purpose so
word[:2] + word[2:]
word[:3] + word[3:]
# negatives with slicing?
# what you think we get
word[-2:]
# Way to think about it, numbers are the boundaries, take everything in between
# +---+---+---+---+---+---+
# | P | y | t | h | o | n |
# +---+---+---+---+---+---+
# 0 1 2 3 4 5 6
# -6 -5 -4 -3 -2 -1
word[-4:-1]
# out of bounds on slice? Gracefully handled.
word[4:42]
word[42:]
# strings are immutable!
#word[0] = 'C'
#word[2:] = 'py'
# have to create a new one
'C' + word[1:]
word[:2] + 'py'
# immutability. Some things in Python provide both a mutable (bytearray) and immutable version. Immutable has usage, for example, for hasing (a topic for latter)
# length (also for lists)
long_word = 'antidisestablishmentarianism'
len(long_word)
# unicode (python 2 is not unicode by default)
greek = 'αβγ'
#while condition :
# (tabbed) statements
# condition: C style boolean operators
# tabbed: space is significant.
# * Avoid mixing tabs and spaces, Python relies on correct position
# and mixing may leave things that look indented correctly, but are not
# * http://www.emacswiki.org/emacs/TabsAreEvil
#
# How might you compute fibonacci (while number is less than 10)?
last = 0
current = 1
while last < 10 :
print(last)
temp = current
current = last + current
last = temp
# Python improvement 1) multiple assignment
# first is in C++, other is not
last, current = 0, 1
while last < 10 :
# need to indent
print(last)
# no temp!!! All, rhs is evaluated before any actual assignment
last, current = current, last + current
# conditions
# * boolean: True, False
while True :
print('Do not do this: ^C to stop')
while False :
print('Never executed')
# * integer: 0 False, True otherwise
count = 10;
while count :
print(count)
count -= 1
# * sequence: len() == 0 False, True otherwise
sequence = ['bar', 'foo']
while sequence :
print(sequence[-1])
tos = sequence.pop()
# Python supports usually comparisons and
# 'and', 'or' and 'not'(C++ has these, but have different precedence)
# https://docs.python.org/3/library/stdtypes.html
# notice that ! is not suppported. Python 2 had <> as well (!=)
# conditions can be chained (but are ands)
x = 1
y = 2
z = 3
x < y <= z
# print is a bit ugly...
# Here is simple print usage: Multiple arguments are handled
# They are space separated, no quotes for strings, and ending in a newline
print("256 ** 2:", 256 ** 2)
last, current = 0, 1
while last < 10 :
# We can specifiy the end character (this is a keyword argument, more when we see functions)
print(last, end=',')
last, current = current, last + current
# pass is basiclly a noop statement. Fills blocks with nothing
while True :
pass
# Someone asked about infinite making of nested lists
# bad_list = []
# while True :
# new_list = []
# new_list.append(bad_list)
# bad_list = new_list
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment