Unless specified otherwise, the following is written for Python 3.
- Python is indentation-based language i.e. indentation defines scope
- Paramenters in Python function are passed by reference so modifying their attributes within the function will change them.
python some_code.py # interpets python code
Python has a -m
command-line flag which when used will import a module or package for you, then run it as a script
python -m http.server 8080 # runs python localhost:8080 using http.server module script
python -m -v doctest filename.py # doctests are a quick way of writing tests (v: verbose)
When you don't use the -m
flag in regular scenarios, the file you named is run as just a script.
See here for the purpose of the shebang (#!
) in Unix systems. You may include the shebang at the top of a Python script to execute it without having to type python
before the code name when running the code from the terminal. After proper configuration of the file manager, shebang also allows for running a python script via double-clicking its file within the file-manager interface.
For latest version of Python 3 scripts:
#!/usr/bin/env python3
For latest version of Python 2 scripts:
#!/usr/bin/env python2
For both Python 2 and 3 scripts (NOT RECOMMENDED):
#!/usr/bin/env python
# Single line comment
"""
Multiple
Line
Comment
"""
Unlike other languages such as C, C++, Java, Javascript etc. Python does not require semi-colons to terminate statements. Semicolons are instead used to delimit statements if you wish to put multiple statements on the same line. For example:
var_1 = 1; var_2 = 2; var_3 = 3;
\
is the continuation character. The line following the continuation character is considered a continuation of the current line:
print("hello" + \
"word")
if x not in range(8) or \
y not in range(3):
def main():
# do something
if __name__ == "__main__": main()
Python uses the following modes when invoking the open()
function:
r
: read (default)rb
: read bytesw
: writewb
: write bytesr+
: read and write
File objects contain a special pair of built-in methods: __enter__()
and __exit__()
. When a file object's __exit__()
method is invoked, it automatically closes the file. Files are typically opened and closed with the following commands:
some_file = open(some_file_path, mode) # opening a file
some_file.close() # closing a file
some_file.closed # check if a file is closed
The opening and closing of a file can be conveniently handled with a with-as clause:
with open(some_file_path, mode) as some_file:
# do something with some_file
Note: some_file
is automatically closed when the with-as clause upon completion of the containing block. It is also closed when a return
is made from within the block.
Read the entire file as a string (or otherwise)
with open(some_file_path, mode) as some_file:
file_contents = some_file.read()
Read the file line by line:
with open(some_file_path, read_mode) as some_file:
for line in some_file:
# do something with line
contents = 'something'
with open(some_file_path, write_mode) as some_file:
some_file.write(contents)
Note: During the I/O process, data is buffered. this means that it is held in a temporary location before being written to the file. Python doesn't flush the buffer—that is, write data to the file—until it's sure you're done writing One way to do this is to close the file. If you write to a file without closing, the data won't make it to the target file.
print("Welcome to Python!") # ends with newline
print("Welcome to Python!", end='') # ends without the default ending newline
print(str1, str2) # prints the 2 strings separated by a space
print(lst) # prints an list
See here for more info.
name = raw_input("What is your name?") # read in string
num = int(raw_input("give a number")) # read in number
name = input("What is your name?") # read in string
num = float(input("give a number")) # read in number
if condition_1:
# do something 1
elif condition_2:
# do something 2
else:
# do something else
Note: There are no switch statements in Python
x = 10 if a > b else 11
This is analogous to the more common conditional assigment syntax in other languages:
x = a > b ? 10 : 11
type('spam') #=> <type 'str'>
type(1) is int #=> True
int('1010', 2) #=> 2 # cast from binary to decimal int
str(2) #=> "2" # cast to string
float(2) #=> 2.0 # cast int 2 into float
bin(10) #=> 0b1010
10 == 0b1010 #=> True
myBool = True
x and y # CONJUNCTION
x or y # DISJUNCTION
not x # NEGATION
Note that they return in decimal format
x | y # bitwise OR of x and y
x ^ y # bitwise EXCLUSIVE OR of x and y
x & y # bitwise AND of x and y
~x # NOT of the bits of x
x << n # x shifted left by n bits
x >> n # x shifted right by n bits
x + y # sum of x and y
x - y # difference of x and y
x * y # product of x and y
x / y # quotient of x and y
x // y # floored quotient of x and y
x % y # remainder of x / y
-x # x negated
+x # x unchanged
x ** y # x to the power y
See PEP 238 regarding floor division operator.
Python contains useful inbuilt math functions
a = [2,3,4,5]
max(a) #=> 5
min(a) #=> 2
sum(a) #=> 14
abs(-1) #=> 1
pow(x, y) #=> x ** y
divmod(x, y) #=> (x // y, x % y)
complex(re, im) # a complex number with real part re, imaginary part im. im defaults to zero.
c.conjugate() # conjugate of the complex number c
s = "String" # single-line string
s = '''This is a
mutli-line string'''
s[0] #=> 'S' # retrieve character
s[1:4] #=> 'tri' # slice
len(s) #=> 6 # string length
s.lower() #=> "string" # downcase
s.upper() #=> "STRING" # upcase
s.isalpha() #=> True # Alpha numeric check
s.startswith('Str') #=> True
s.endswith('ing') #=> True
'hello ' + 'world' #=> 'hello world' # concatenation
','.join('abc') #=> 'a,b,c'
','.join(['a', 'b', 'c']) #=> 'a,b,c' # For this to work, the argument has to be a list of strings
Old style not recommended:
'%s %s' % ('one', 'two') #=> 'one two'
'%d %d' % (1, 2) #=> '1 2'
'%2.2f%%' % (0.93788 * 100) #=> '93.79%'
New recommended style:
'{} {}'.format('one', 'two') #=> 'one two'
'{} {}'.format(1, 2) #=> '1 2'
'{0} {0} {1}'.format(1, 2) #=> '1 1 2'
for i in some_list:
# do something
The else block will execute only when the loop condition is evaluated to False
. i.e. it will only run once at the end
for number in numbers:
# do something
else:
# do something else
while condition:
# do something
Just like for-else loops, the else block is executed only when the while-loops terminates formally
while condition:
# do something
else:
# do something else
break # breaks out of current loop
continue # continues to next iteration in loop
These are some common data structures used in Python
In python, lists are variable length arrays much like ArrayList
in C++ and Vector
in Java. Lists offer random access and has similar time complexities (see here) as variable length arrays in other languages. For the sake of consistency, we shall reserve the variable lst
to refer to a list in the given context.
lst = [5, 6, 7, 8] #=> [5, 6, 7, 8] # explicit assignment
lst = [1] * 4 #=> [1, 1, 1, 1] # generative assignment
lst = list(range(5,9)) #=> [5, 6, 7, 8] # generative assignment using range
lst = [x for x in range(5,9)] #=> [5, 6, 7, 8] # generative assignment using range and list comprehension (see list comprehension section below)
# Explicit assignment
lst = [[1,2,3],[4,5,6]] #=> [[0, 0], [0, 0], [0, 0]]
# Generative assignment
cols = 2; rows = 3
lst = [[0] * cols for i in range(rows)] #=> [[0, 0], [0, 0], [0, 0]]
Caveat (see here):
cols = 2; rows = 3
lst = [[0] * cols] * rows #=> [[0, 0], [0, 0], [0, 0]]
lst[0][1] = 1
print(lst) #=> [[0, 1], [0, 1], [0, 1]]
range(start, stop, step)
provides a convenient construct for generating an ordered list of numbers
range(6) #=> [0,1,2,3,4,5]
range(1,6) #=> [1,2,3,4,5]
range(1,6,3) #=> [1,4]
range(10,-1,-1) #=> [10,9,8,7,6,5,4,3,2,1,0]
3 in range(1,4) #=> True
3 not in range(1,4) #=> False
lst.count(item) # counts the number of times item appears in list
lst.index(item) # returns index of first occurence of the item
lst.insert(index, item) # inserts item at position index, suceeding elements are pushed down | in-place | does not return
lst.append(item) # append item to end of list | in-place | does not return
lst.remove(item) # remove item | in-place | does not return
lst.pop(index) # removes object at index and returns it (if not index provided, will pop last) | in-place | returns popped item
del(lst[index]) # same as pop exept it doesn't return the object
del lst[index] # same as above
Slicing is achieved with the [start:end:stride]
operator
start
describes where the slice starts (inclusive)- If not provided, value defaults to 0
end
is where it ends (exclusive)- If not provided, value defaults to length of list. I.E. Operation defaults to
[start:length:1]
- If value is negative, Python interpreter will subtract that value off the length of list. For example
a[start:-x]
is translated tolst[start:length-x]
- If not provided, value defaults to length of list. I.E. Operation defaults to
stride
indicates the interval between items in the sliced list- If not provided, value defaults to 1. I.E. Operation defaults to
[start:end:1]
start
andend
defines the sequence for stride to traversestride
indicates the interval in sequence for which objects are picked. For example, a stride of 2 will skip 1 item in sequence at every interval.- a positive stride length traverses the sequence in sequential order
- a negative stride traverses the sequence in reverse order
- If not provided, value defaults to 1. I.E. Operation defaults to
lst = [0, 1, 2, 3, 4, 5, 6, 7, 8 ,9]
lst[:2] #=> [0, 1]
lst[3:6] #=> [2, 3, 4]
lst[:-5] #=> [0 ,1, 2, 3, 4] # Python interpreter translates to lst[0:5]
lst[::2] #=> [0, 2, 4, 6, 8]
lst[::-1] #=> [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
lst1 = [1, 2, 3]
lst2 = [4, 5, 6]
lst1 + lst2 #=> [1, 2, 3, 4, 5, 6]
List comprehension is commonly used as a shorthand for creating a new list by iterating over a given list.
It is commonly used as a filter by applying a condition over the given list:
a = [1, 2, 3, 4]
odd_a = [x for x in a if i%2 == 0] #=> [2, 4]
It is also commonly used for modifying each item in the given list:
a = [1, 2, 3, 4]
squared_a = [x**2 for x in a] #=> [1, 4, 9, 16]
squared_even_a = [x**2 if x%2 == 0 else x for x in a] #=> [1, 4, 3, 16]
We can also nest lists within the comprehension to iterate through multi-dimensional lists. One application for this is to flatten out a multi-dimensional list:
lst_2d = [[1, 2, 3], [4, 5, 6]]
flattened_lst = [x for row in lst_2d for x in row ] #=> [1, 2, 3, 4, 5, 6]
To iterate over all items in the list:
for item in lst:
# do something with item
To iterate over all indices for items in the list:
for index in range(len(lst)):
# do something with index
To iterate over all indicies and their accompanying items in the list:
for index, item in enumerate(lst):
# do something with index, item
To iterate all items in the list in reversed order (without using slice):
for item in reversed(lst):
# do something with item
use zip
to iterate over multiple lists at once (terminating on the shorter list):
for item_1, item_2, item_3 in zip(lst_1, lst_2, lst_3):
# do something with item_1, item_2, item_3
lst.sort() # in-place sorting
tuples = [(5,99), (4,54), (3,12), (2,44)]
sorted(tuples) # returns (2,44), (3,12), (4,54), (5,99)
sorted(tuples, key=lambda x: x[1]) # returns (3,12), (2,44), (4,54), (5,99)
In Python dictionary is equivalent to hashmap
Declaring an empty dictionary:
dic = {}
dic = dict() # using contructor
Declaring and initializing with values:
dic = {'key_1' : val_1, 'key_2' : val_2} # via explicit assignment
dic = dict([('key_1', val_1), ('key_2', val_2)]) # via key,val pair list
dic = dict(key_1=val_1, key_2=val_2) # via keyword arguments
dic = {x: x**2 for x in (1, 2, 3)} # via dict comprehensions
Common methods to check and update members
key in dic # check if key is in dic
dic[key] = value # adding/updating value. Note key can be a number
del dic[key] # delete (key, val) from dic
Common methods to extract members:
dic.items() # returns an list of (key, value) tuples, not in any order
dic.keys() # returns an list of keys, not in any order
dic.values() # return an list of values, not in any order
# Iterates each key (not guaranteed same order everytime)
for key in hashmap:
# Do something with key
# Iterates each key, value pair
for key, value in hashmap.items():
# Do something with key, value
To get a sorted list of keys:
sorted(hashmap)
dic = {'a': 1, 'b': 2, 'c': 3}
[value for (key, value) in sorted(dic.items())] #=> [1, 2, 3]
import math # import math module
from datetime import datetime # import datetime function from datetime module
from math import * # import all functions from math module into global namespace
Note of caution for from math import *
: If you have a function of your very own named sqrt and you import math
, your function is safe: there is your sqrt
and there is math.sqrt
. However if you do from math import *
, you have a problem, namely, two different functions with the exact same name.
To return an list of strings listing all the function names in module:
dir(module)
import os
os.getcwd() # get current working directory
os.chdir("d/jinzhe") # change directory
os.listdir(".") # list files in current working directory
os.path.join(par_dir, rel_path) # join par_dir and rel_path together
os.path.abspath(rel_path) # get the absolute path give relative path
import sys
Getting arguments:
sys.argv[1] # first argument
Pythonpath stores the list of directories Python scans through when locating modules and files. You may append directories to your Pythonpath via sys.path.append
instead of appending to $PYTHONPATH
environment variable:
sys.path.append(some_path)
See here for all available arugments of add_argument()
method
import argparse
parser = argparse.ArgumentParser(description="Description of script")
parser.add_argument('--flag', '-f', action='store_true')
parser.add_argument('--input', '-i', type=int, default=1, help='Help text for input argument')
args = parser.parse_args()
args.flag # gets boolean if flag was indicated
args.input # gets argument for --input
import cPickle as pkl
loaded_pickle = pkl.load(open(pickle_path, "r" )) # loading
pkl.dump(payload, open(pickle_path, "w" )) # dumping
import pickle as pkl
loaded_pickle = pkl.load(open(pickle_path, "rb" )) # loading
pkl.dump(payload, open(pickle_path, "wb" )) # dumping
from collections import defaultdict
# int type: non-existent keys will have default value 0 when first called
dic = defaultdict(int)
dic[key] += n
# list type: non-existent keys will have default value list() when first called
dic = defaultdict(list)
dic[key].append(n)
# set type: non-existent keys will have default value set() when first called
dic = defaultdict(set)
dic[key].add(n)
TODO
from collections import namedtuple
TODO
from collections import OrderedDict
import re
re.search(r'\d+\.\d*N','1.312740N, 103.779490E').group(0) #=> '1.312740N'
import datetime
date = datetime.now() # current date and time
date.year
date.month
date.day
date.hour
date.minute
date.second
from random import randint
randint(low, high) # generates random interger between low to high inclusive
from enum import Enum
class EdgeDetector(Enum):
prewit = 0
sobel = 1
See API
Importing:
from multiprocessing import Pool
Pool:
pool = Pool() # If processes is None then the number returned by multiprocessing.cpu_count()
# do something
pool.close()
# Using `with` clause
with Pool(processes=4) as pool:
# do something
- Make sure function is defined before Pool istantiates! Otherwise the worker cannot see the function
Using pool.apply_async
:
result_1 = pool.apply_async(f, 1) # evaluate `f(1)` asynchronously
result_2 = pool.apply_async(f, 2) # evaluate `f(2)` asynchronously
answer_1 = result_1.get(timeout=10)
answer_2 = result_2.get(timeout=10)
Using pool.map
:
result_1, result_2 = pool.map(f, [1,2])
- This function only works for single argument functions! Use a function wrapper which takes in a single tuple if parallelizing multi argument functions
from multiprocessing import Pool
def f(arg):
# do something
args_list = [1,2,3,4]
for arg in args_list:
p = Process(target=f, args=(arg,))
p.start()
p.join()
The default function return value in Python is None
def some_function(param_1, kwarg_1=default_kwarg_1_val):
# do something
return ans
lst = [0, 1, 2, 3, 4, 5, 6]
filter(lambda x: x % 3 == 0, lst) #=> [0, 3, 6]
There are multiple ways to declare a class.
Python 3: Delcare a class with implicit inheritance of object
class:
class MyClass:
pass
Python 3: Declare a class with implicit inheritance of object
class:
Python 2: Declare an old-style class:
class MyClass():
pass
Python 3: Declare a class with explicit inheritance of object
class:
Python 2: Declare a new-style class:
class MyClass(object):
pass
See here on old-style and new-style classes
my_class_object = MyClass(attr1, attr2, attr3) # instantiating MyClass
The first argument __init__()
gets is used to refer to the instance object by convention, that argument is called self
. If you add additional arguments in the body of __init__()
, you need to give each instance those attributes. self
is only passed as an argument when defining methods, but are left out when calling them.
By providing a return value in this method, we can tell Python how to represent an object of our class (for instance, when using a print statement)
__repr__(self):
return "(#{}, #{}, #{})" % (self.attr_1, self.attr_2, self.attr_3)
class MyClass(object):
# class attributes or "member variables", information that belongs to the class object
attr_1 = attr_1_val # Note: must be referenced later via self.attr_1
# constructor with instance attributes
def __init__(self, attr1, attr2, attr3):
self.attr1 = attr1
self.attr2 = attr2
self.attr3 = attr3
# methods (need to pass in self)
def method_1(self, param_1, param_2):
# do something
class MyOtherClass(MyClass):
# new constructor
def __init__(self, attr1, attr2, attr3, attr4):
super(MyOtherClass, self).__init__(attr1, attr2, attr3) # super method (don't have to include self)
self.attr4 = attr4
# override method_1 from MyClass
def method_1(self):
# do something new
def old_method_1(self):
return super(MyOtherClass, self).method_1() # super method. Note the return statement
def func(**kwargs):
# do stuff with kwargs['a'] and kwargs['b']
func(a=1, b=3)
def func(a, b):
print(a, b)
func(**{'a': 1, 'b': 2}) # same as func(1, 2)
#=> 1 2
Tuples are immutable in Python
uniple = (1,)
pair = (1, 2)
triplet = (1, 2) + (3,) # creates a new tuplet
len(some_object) # returns length attribute of the object
Exception | Description |
---|---|
IOError |
Raised when a file cannot be opened |
ImportError |
Raised when python cannot find the module |
ValueError |
Raised when a built-in operation or function receives an argument that has the right type but an inappropriate value |
ZeroDivisionError |
Raised when division by zero occurs |
EOFError |
Raised when one of the built-in functions (input() or raw_input()) hits an end-of-file condition (EOF) without reading any data |
KeyboardInterrupt |
Raised when the user hits the interrupt key (normally Control-C or Delete) |
ValueError |
Raised when a built-in operation or function receives an argument that has the right type but an inappropriate value |
See Built-in Exceptions for the full list of Python exceptions that come out of the box.
try-except:
try:
# something dangerous
except IOError:
# do something
except (RuntimeError, TypeError, NameError): # multiple exceptions
# do something
# Generic exception: Catches all exceptions
except Exception as e: # access exception variable with `as e`
# do something. e.g `print(str(e))`
Else:
try:
# something dangerous
except KeyboardInterrupt:
# do something
# ONLY WHEN preceding except clauses did not catch anything
else:
# do something
# NOTE: Code in this block may raise exceptions of its own
Finally:
try:
# something dangerous
except KeyboardInterrupt:
# do something
else:
# do something
# Always executed before leaving the try statement, regardless if an exception occurred or not
finally:
# do something
Raising pre-defined exceptions:
raise IOError
raise SyntaxError("Oops!") # Add a custom message
Raising custom exception:
class MyException(Exception):
pass
raise MyException("Truly exceptional!")