In [144]:
import sys
sys.argv[0]
Out[144]:
In [145]:
sys.argv
Out[145]:
In [146]:
type(7)
Out[146]:
In [147]:
type(4.5)
Out[147]:
In [148]:
print(12/4)
print(type(12/4))
type(12/4)
Out[148]:
In [149]:
print(12//4)
type(12//4) # floor division
Out[149]:
In [150]:
print(12%4)
type(12%4)
Out[150]:
In [151]:
2 ** 4
Out[151]:
In [152]:
# Using a var without assigning a value yields a NameError
width
In [ ]:
2 * 2.5 + 2
In [ ]:
#_ should be treated as read_only.
# It can be assigned to, but then you won't have a magic variable anymore
_ # if need to access last thing that was returned
In [ ]:
3j + 5
In [ ]:
3J + 5
In [ ]:
type(3J) # j is the impaginary part of the complex number
In [ ]:
1.J
In [ ]:
# Remove issues with quote escaping
print(r'whoa\\yay.com')
In [ ]:
#Otherwise leaving it out means you consider backslash an escape character
print('whoa\\yay.com')
In [ ]:
'''who
oo
oo'''
In [ ]:
# Remove end of line characters by prefacing with 1 backslash in a multiline comment
print("""\
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
""")
In [ ]:
'ho' * 3 + ' merry xmas'
In [ ]:
# 2 adjacent string literals are concatenated when they are interpreted
'py' 'thon'
In [ ]:
prefix = 'py'
prefix 'thon'
In [ ]:
prefix = 'py'
prefix + 'thon'
In [ ]:
# Can put long strings in a row
(
'There are lots '
'of strings '
'in a row'
)
In [ ]:
# Indexing: 1 char at an index
'python'[0]
In [ ]:
'python'[-1]
In [ ]:
# Slicing: Multiple chars at specified indices
In [ ]:
'python'[1:3]
# index includes char at 1st index, includes all chars up to and excluding
# last index
In [ ]:
'python'[:3] + 'python'[3:]
In [ ]:
'''
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
'''
In [ ]:
'python'[50]
In [ ]:
# Handles gracefully
'python'[:50]
In [ ]:
'python'[0] = 'a' # Strings are immutable
In [ ]:
newword = 'python'[:2] + 'k' + 'python'[3:]
newword
In [ ]:
# Lists, dictionaries etc are COMPOUND data types.
# Lists can have items of different types.
# Slicing creates a shallow copy of the list
In [ ]:
nummys = [[1],[2],[3],[4],[5]]
nummys[:]
In [ ]:
nummys[3] = 1000
nummys
In [ ]:
nummys.append(50)
nummys
In [ ]:
nummys[2:] = [] # assigning to a slice updates the original list
nummys
In [ ]:
nummys[:] = []
nummys
In [ ]:
nummys = [[1,2],[5,6]]
nummys[0][1]
In [ ]:
# multiple assignment, unpacks values from list into variables
# otherwise you get a value error
# rhs of expression is evaluated first, left to right
a, b = nummys
b
In [ ]:
while 0: # 0 is false, any other number is True
print('yay!')
if 1==1:
break
In [ ]:
while 0.1:
print('yay!')
if 1==1:
break
In [ ]:
# any value that is has length > 0 is true, else it's false
if []:
print('yay')
In [ ]:
if [0]:
print('yay')
In [ ]:
# print function handles multiple args, floating points, and strings differently
print([[5.]])
In [ ]:
i = 5
print('its', i) #puts a space for you
In [154]:
# for statements: iterates over items of any sequence in the order they appear.
# using a slice copies the array for you
words = ['pauline', 'is', 'cool']
for w in words[:]:
words.insert(0, len(w))
print(words)
In [158]:
# range generates arithmetic progressions
list(range(8))
Out[158]:
In [159]:
type(range(8))
Out[159]:
In [161]:
list(range(2,8))
Out[161]:
In [163]:
list(range(2,8,-2))
Out[163]:
In [164]:
# its better to use enumerate instead of range(len(w))
for index, value in enumerate([1,2,3]):
print(index, value)
In [165]:
# The range object behaves as a list, but its just an object that returns successive items of the
# right sequence when you iterate over it.
# By not making the list right away, it saves space.
# the range object is an 'iterable'.
# It's something that can be a target for funcions/constructs that expect something from which they can get
# successive items until the end.
#list() creates lists from iterators
for a in list(range([1,2,3])):
print(a)
In [168]:
words = ['one', 'two', 'three']
for i, w1 in enumerate(words):
for j, w2 in enumerate(words):
if i == j:
print(i, 'equals!!')
#break
else:
print(j, 'sheeeeit')
In [169]:
for a in range(8):
if a % 2 == 0:
print('whoa')
else:
print('doneskis')
In [174]:
for i in range(6):
if i % 2 == 0:
print(i, 'whoa')
elif i == 5:
break
else:
print('doneskis') #if a break statement is executed, else block won't be executed.
In [175]:
for i in range(5):
if i % 2 == 0:
continue
print(i)
In [177]:
# use pass for method stubs so they can compile
if 1==1:
pass
In [179]:
def new_func():
'''
docstring
'''
return 2*2
new_func()
Out[179]:
In [189]:
### function definitions create a new symbol table for local vars.
### variable references are first checked in this symbol table, then the
### symbol table of the outer scope, and so on until its global, then in the table of built-in names.
# globals can't be directly assigned a value in a function.
a = 2
def f():
#print(a)
a = 7
print(a)
f()
print(a)
In [195]:
# args are passed via call by value. The value is the reference of the object, not the actual object, added to symbol table
def change_list(lst):
lst.append(4)
my_list = [1,2,3]
change_list(my_list[:]) #shallow copy
print(my_list)
change_list(my_list)
print(my_list)
In [203]:
# functions return values, procedures do not (except in python it returns None, so I guess it is a function)
# methods are functions that belong to an object - it's a function enclosed within an object
# can have default values
def is_this_ok(answer='Yes'):
if answer=='No':
raise ValueError('EVERYTHING IS NOT OK')
return answer
print(is_this_ok())
print(is_this_ok('No'))
In [206]:
global_thing = 9
global_thing = 7
def g(a=global_thing):
print(a)
g(4)
global_thing = 8 #default variables are evaluated at the point of function definition in the defining scope
g()
In [207]:
#default value is evaluated only once.
def h(a=[]):
a.append(1)
return a
h()
Out[207]:
In [208]:
h()
Out[208]:
In [209]:
def g(h=None):
if h is None:
h = []
h.append(1)
return h
print(g())
print(g())
In [212]:
# args, kwargs. a keyword argument is def(a=None), a positional argument is def(x,y)
# kwargs are optional arguments, args are required.
# kwargs have to follow positional arguments.
def f(lungs=2, hearts):
print(lungs, hearts)
In [218]:
def f(*arguments):
print(arguments)
#numbers = [1,2,3]
f(1,2,3)
In [224]:
def g(**kwargs): # turns the keyword arguments into a dictionary
return kwargs
my_dict = g(i=1, j=2)
print(my_dict['i'])
my_dict
Out[224]:
In [225]:
# arbitrary arg lists
# * indicates a variatic argument, any args after this must be kwargs.
def h(*args, sep="/"):
return sep.join(args)
h('1', '2', '3')
Out[225]:
In [227]:
# unpacking arg lists
# lists in a tuple, but need unpacking for a function that needs separate pos args.
args = [1,2,3]
list(range(*args))
Out[227]:
In [230]:
d = { 'volts':1, 'current': 2}
def converter(volts, current=3):
print(volts, current)
converter(**d)
In [239]:
# lambda functions are small and anonymous. Used where you can use regular functions, if they have a single expression.
fired = lambda x: x + 5
fired(1)
Out[239]:
In [245]:
pairs = [(1, 'one'), (2, 'two'), (3, 'three')]
pairs.sort(key=lambda pair: pair[1]) #sort alphabetically on the 2nd index of the tuple
pairs
Out[245]:
In [261]:
def my_lambda(n):
"""Summary
Describe calling conventions, side effects, etc. """
return lambda x, y: x + y + n
my_lambda(1)(2, 3)
Out[261]:
In [262]:
print(my_lambda.__doc__) # get the docstring from the function attribute
In [270]:
# Function annotations: optional metadata about types in user defined functions.
def f(ham: str, eggs: str = 'eggs') -> str:
print('Annotations', f.__annotations__)
print(args)
return ham + ' ' + eggs
f('hhham')
Out[270]:
https://www.python.org/dev/peps/pep-0008/
In [293]:
# Add item
my_list = [1, 2, 3, 4, 5]
print(my_list)
my_list.append(6)
my_list
Out[293]:
In [294]:
# Add elements from an iterable to the end of the list
my_list = [1, 2, 3, 4, 5]
print(my_list)
my_list.extend(range(10, 5, -2))
my_list
Out[294]:
In [299]:
# Insert at a particular index
my_list = [1, 2, 3, 4, 5]
print(my_list)
my_list.insert(-1, -1)
my_list.insert(0, -1)
my_list
Out[299]:
In [301]:
my_list = [1, 2, 3, 4, 5]
print(my_list)
my_list.remove(1) # error if doesn't exist
my_list
Out[301]:
In [309]:
my_list = [1, 2, 3, 4, 5]
print(my_list)
my_list.pop() # pops last value off the stack
print(my_list)
my_list.pop(0) # pops first value off the stack if index specified
print(my_list)
In [317]:
my_list = [1, 2, 3, 4, 5]
print(my_list)
del my_list[:] # my_list is now empty, removes all elements
print(my_list)
#del my_list # completely removes the name reference as well
my_list = [1, 2, 3, 4, 5]
print(my_list)
my_list.clear()
my_list
Out[317]:
In [322]:
my_list = [1, 2, 3, 4, 5]
index = my_list.index(4)
print(index)
index = my_list.index(3, 2, 4) # find an elem within a substring
print(index)
In [323]:
my_list = [1, 2, 3, 4, 5, 5]
my_list.count(5)
Out[323]:
In [327]:
my_list = [5, 1, 2, 3, 4]
print(my_list)
my_list.sort()
print(my_list)
my_list.sort(reverse=True)
print(my_list)
In [331]:
my_list = [(5, 1),(2, 3), (4, 6)]
my_list.sort() # looks at the first elem
print(my_list)
my_list.sort(reverse=True)
print(my_list)
my_list.sort(key=lambda x: x[1], reverse=True) #sorts in reverse based on the 2nd elem
print(my_list)
In [332]:
my_list = [1, 2, 3, 4, 5]
my_list += my_list.copy() #same as my_list[:]
my_list
Out[332]:
In [342]:
# Turn a list into a stack - only use pop and append. This is efficiently implemented in python lists.
lst = []
lst.append(1)
lst.append(2)
print(lst)
lst.pop()
lst
print(lst)
lst
Out[342]:
In [343]:
# Lists don't make a good FIFO queue - it's not very efficient.
_
Out[343]:
In [ ]: