epsilon = 0.0000001
def square_root(a):
x = a / 2.0
while True:
y = (x + a / x) / 2
if abs(y - x) < epsilon:
break
x = y
return y
def test_square_root():
import math
for i in range(1, 10):
mine = square_root(i)
theirs = math.sqrt(i)
delta = abs(mine - theirs)
print("%3.1f %-13.11g %-13.11g %.11g" % (float(i), mine, theirs, delta))
test_square_root()
1.0 1 1 1.1102230246e-15
2.0 1.4142135624 1.4142135624 2.2204460493e-16
3.0 1.7320508076 1.7320508076 0
4.0 2 2 0
5.0 2.2360679775 2.2360679775 0
6.0 2.4494897428 2.4494897428 8.881784197e-16
7.0 2.6457513111 2.6457513111 0
8.0 2.8284271247 2.8284271247 4.4408920985e-16
9.0 3 3 0
(For details about the formatting used in the print statement see
String Formatting Operations
that was discussed in last week's lecture.)
def average_coord(code):
f = open(code, 'r')
sum_x = sum_y = sum_z = 0.0
num_atoms = 0
for line in f:
if not line.startswith("ATOM"):
continue
sum_x += float(line[30:38]) # get only the X coordinate of the record
sum_y += float(line[38:46]) # ditto for Y
sum_z += float(line[46:54]) # ditto for Z
num_atoms += 1
if num_atoms == 0:
print("no atoms were found")
else:
avg_x = sum_x / num_atoms
avg_y = sum_y / num_atoms
avg_z = sum_z / num_atoms
print("average coordinates of ", num_atoms, "atoms:", avg_x, avg_y, avg_z)
f.close()
average_coord(input('PDB entry: ').strip())
average coordinates of 1102 atoms: 21.8288139746 5.7510508167 95.3145789474
def open_pdb(code):
url = "https://files.rcsb.org/view/%s.pdb" % code
from urllib.request import urlopen
from io import TextIOWrapper
# urlopen returns a binary stream, so we convert it for text I/O
return TextIOWrapper(urlopen(url))
def average_coord(code):
f = open_pdb(code)
# Everything else is the same as before
Object Type | Examples |
---|---|
Numbers | 3.1416, 42, 123456789 |
Strings | 'pc204', "Joe's story" |
Files | text = open('eggs', 'r').read() |
Lists | [1, [2, 'three'], 4] |
Tuples | (1, 'spam', 4, 'U') |
Dictionaries | {key: value, 'food': 'spam'} |
Sets | {key, 'food'} |
Constant | Interpretation |
---|---|
1234, -24, 0 | Integers |
1.23, 3.14e-10, 0.0 | Floating point number |
0177, 0x9ff | Octal and hexadecimal constant |
3+4j, 3.0+4.0j, 3J | Complex number constants |
print("%.20f" % (0.1 + 0.2))
0.30000000000000004441
>>> if ((0.1 + 0.2) != 0.3):
>>> print("How can this be?")
How can this be?
>>> epsilon = 1.0e-14
>>> if (abs((0.1 + 0.2) - 0.3) > epsilon):
>>> print("How can this be?")
Operation | Interpretation |
---|---|
L1 = [ ] | Creates an empty list |
L2 = [0, 1, 2, 3] | A four element (or item) list |
L3 = ['one', 'two', [1, 2]] | Nested sublists |
L2[2] | Third item in a list (like string offsets, list offsets begin at 0) |
L3[2][0] | First sublist item in the third list item |
L2[i:j] | Slice (just like in strings) |
len(L3) | Length (just like in strings) |
L1 + L2 | Concatenation |
L1 * 4 | Repetition |
for x in L2: | Iteration |
'two' in L3 | Membership test |
Operation | Interpretation |
---|---|
L2.append(4) | Grow list at end by 1 item (the integer 4) |
L2.extend([1, 2, 3]) | Grow list at end by multiple items |
L2.sort() | Sort the list |
L2.index(n) | Find index of 'n' in list |
L2.reverse() | Reverse items in the list |
del L2[k] | Remove kth item from the list |
L2[i:j] = [ ] | Remove ith through (j-1)th items |
L2[2] = 42 | Replace 3rd item in the list (index assignment) |
L2[1:3] = [0, 0] | Replace 2nd & 3rd list items with zeros (slice assignment) |
>>> L1=[1, 2, 3, 4]
>>> L2=[5, 6]
>>> len(L1)
4
>>> L1[1:3] # indexing begins at 0!
[2, 3]
>>> L1[:3] # missing first index means from the beginning
[1, 2, 3]
>>> L1[2:] # missing second index means through end of the list
[3, 4]
>>> L1[0:-1] # -1 means one less item than the last item
[1, 2, 3]
>>> L1 + L2
[1, 2, 3, 4, 5, 6]
>>> L1.append(L2)
>>> L1
[1, 2, 3, 4, [5, 6]]
def extract(s):
"""extract space-separated words from string 's' and
return each word in a list"""
result = [ ] # begin with empty list
while s:
k = 0 # k will be the end of a slice
for c in s: # inspect chars in string one at a time
if c == ' ':
break # exit the loop if character is a space
k = k + 1 # increment slice limit by 1
result.append(s[0:k]) # add a new word to the list
s = s[k+1:] # save the remaining string
return result # done - return the list to the caller
>>> print(extract('Now is the time for all good people'))
[’Now', 'is', 'the', 'time', 'for', 'all', 'good', 'people']
>>> print(extract('Now')) # how about with just one word in s?
[‘Now’]
>>> print(extract('')) # test for correct result with null string
[ ]
>>> print(extract(' ')) # a string with three spaces
['', '', '']
def extract(s):
"""extract space-separated words from string 's' and
return each word in a list"""
result = [ ] # begin with empty list
while s:
k = 0 # k will be the end of a slice
for c in s: # inspect chars in string one at a time
if c == ' ':
break # exit the loop if character is a space
k = k + 1 # increment slice limit by 1
if k != 0: # ONLY ADD A NEW WORD IF ONE WAS FOUND
result.append(s[0:k]) # THERE WAS, SO ADD IT
s = s[k+1:] # save the remaining string
return result # done - return the list to the caller
>>> print(extract(' ')) # a string with three spaces
[ ]
>>> print(extract(' Now is the time ')) # spaces sprinkled here and there
['Now', 'is', 'the', 'time']
def instring(w, s): # is word w contained in s?
words = extract(s) # 'words' is now a list of words
for x in words: # consider each, one at a time
if x == w: # test for a match
return True
return False
str = ' Now is the time for all good people '
print(instring('time', str))
True
print(instring('tom', str))
False
print(instring('', str))
False
print(instring('', ''))
False
for x in words:
if x == w:
return True
return False
...and replaced with a membership test...
return w in words # return True if w in words
Functions | Return Value |
---|---|
all(L1) | True if all elements in L1 are True |
any(L1) | True if any element in L1 is True |
min(L1) | Smallest element in L1 |
max(L1) | Largest element in L1 |
reversed(L1) | Elements of L1 in reverse order |
sorted(L1) | Elements of L1 in sorted order |
sum(L1) | Sum of elements in L1 |
sum(L1, start) | Sum of elements in L1 + start |
# Loop through array using indices
for index in range(len(L1)):
value = L1[index]
print(index, value)
for index, value in enumerate(L1):
print(index, value)
# Apply an operation to each element in a list
# and keep the results in a second list
L2 = [ ]
for value in L1:
L2.append(value + 10)
# same using list comprehension
L2 = [ value + 10 for value in L1 ]
# and you can even skip some elements if you want
L3 = [ value + 10 for value in L1 if value < 100 ]
>>> t1 = (1, 2, 3, 4) # this is a tuple
>>> t2 = 5, 6, 7, 8 # this too (syntactically unambiguous)
>>> t3 = (9,) # a one-item tuple (comma required to avoid ambiguity with expressions)
>>> t4 = (9) # an expression that evaluates to 9
>>> t5 = ('abc', (1, 2, 3), 'def') # nested tuples
def trivial():
x = 2.71828
y = 3.14159
return (x, y)
m, n = trivial()
Operation | Interpretation |
---|---|
D1 = { } | Creates an empty dictionary |
D2 = {'tom':1, 'conrad':2} | A two item dictionary |
D3 = {'tom':1, 'conrad':{'greg':3, 'eric':4}} | Nesting |
D2['conrad'] | Retrieval of value by key |
D3['conrad']['eric'] | Nested retrieval |
D2.has_key('tom') or 'tom' in D2 | Membership test |
D2.keys() | List of all keys in the dictionary |
D2.values() | List of all values in the dictionary |
D2.items() | List of all (key, value) pairs |
D2.get(k, v) | Value with key "k" if k in D2, otherwise "v" |
D2.setdefault(k, v) | Like D2.get(), but also adds item to dictionary D2 |
len(D2) | Number of keys in the dictionary |
D2[key] = value | Add or change an item |
del D2[key] | Delete an item |
D4 = D2.copy() | Create a (shallow) copy of D2 |
>>> d1 = {'tom':1, 'conrad':2, 'greg':3, 'eric':4}
>>> d1['greg'] # given a key, fetch associated value
3
>>> len(d1) # return number of items in the dictionary
4
>>> d1.has_key('eric') # test for the presence of a key
True
>>> d1.keys() # return list of all keys
['tom', 'conrad', 'greg', 'eric']
>>> d1['tom'] = 42 # assign a new value for key 'tom'
>>> d1['conrad'] = [3, 4, 5] # items can be arbitrary objects
>>> d1 # note that dictionaries are unordered!
{'conrad': [3, 4, 5], 'greg': 3, 'eric': 4, 'tom': 42}
>>> del d1['greg'] # delete an entry
>>> d1
{'conrad': [3, 4, 5], 'eric': 4, 'tom': 42}
>>> d1['al'] = 'good man' # assigning to a new index adds a new entry
>>> d1
{'al': 'good man', 'conrad': [3, 4, 5], 'eric': 4, 'tom': 42}
>>> d1[101] = 'test' # keys can be any immutable object
>>> d1
{'al': 'good man', 'conrad': [3, 4, 5], 101: 'test', 'eric': 4, 'tom': 42}
>>> s1 = {1, 2, 3, 4} # this is a set
>>> s1
{1, 2, 3, 4}
>>> 3 in s1 # membership test (much faster than a list)
True
>>> if 3 in s1: # similar to above
... print('True')
True
>>> s1.add(5) # add a new element
>>> s1
{1, 2, 3, 4, 5}
>>> s1.add(5) # does nothing since "5" is already a member of the set
>>> s1.remove(4) # remove an element
>>> s1
{1, 2, 3, 5}
>>> s1.discard(4) # like remove but won't cause an exception
>>> s2 = {1, 3}
>>> s1 | s2 # returns union of s1 and s2
{1, 2, 3, 5}
>>> s1 & s2 # returns intersection of s1 and s2
{1, 3}
>>> s1 - s2 # returns difference of s1 and s2
{2, 5}
>>> x = 42 # binds the name "x" to an integer object
>>> x = "pc204" # binds the name "x" to the string object "pc204"
>>> x = [1, 2, 3] # binds the name "x" to a list
>>> y = ['a', x, 'c'] # binds the name "y" to a list which includes an embeded reference to another list
>>> y
['a', [1, 2, 3], 'c']
>>> x[1] = 'b' # modify the second item in the original list
>>> y # ...which of course also changes the object that "y" references
['a', [1, 'b', 3], 'c']
>>> x = [1, 2, 3]
>>> z = x # both x and z reference the *SAME OBJECT*
>>> y = ['a', z, 'c']
>>> y
['a', [1, 2, 3], 'c']
>>> x[1] = 'b' # this still changes the object that "y" references
>>> y
['a', [1, 'b', 3], 'c']
>>> x = [1, 2, 3]
>>> y = x[:] # assigning a slice of the entire list creates a copy of the object
>>> y
[1, 2, 3]
>>> # so now if I modify the original object, like this...
>>> x[1] = 'b' # so now if I modify the original object
>>> x # of course x is changed...
[1, 'b', 3]
>>> y # but y is unchanged...
[1, 2, 3]
>>> # this works for embeded references as well...
>>> x = [1, 2, 3]
>>> y = ['a', x[:], 'c']
>>> x[1] = 'b'
>>> y
['a', [1, 2, 3], 'c'] # the copy of the original object did not change
D1 = {'tom':1, 'conrad':2, 'eric':3, 'greg':4}
D2 = D1.copy()
>>> x = 5
>>> y = ['a', x, 'c']
>>> y
['a', 5, 'c']
>>> x = 10
>>> y
['a', 5, 'c']
x or y | Logical ‘or’ (y evaluated only if x is false) |
x and y | Logical ‘and’ (y evaluated only if x is true) |
not x | Logical negation |
<, <=, >, >=, = =, <>, !=, is, is not, in, not in | Comparison operators, identity tests, sequence membership |
x | y | Bitwise or |
x ^ y | Bitwise exclusive or |
x & y | Bitwise and |
x<<y, x>>y | Shift x left or right by y bits |
x + y, x - y | Addition/concatenation, substraction |
x * y, x / y, x % y | Multiplication/repetition, division, remainder/format |
-x, +x, ~x | Unary negation, identity, bitwise complement |
x[i], x[i:j], x.y, x(...) | Indexing, slicing, qualification, function calls |
(...), [...], {...}, "..." | Tuple, list, dictionary, conversion to string |
and | del | from | not | while |
as | elif | global | or | with |
assert | else | if | pass | yield |
break | except | import | ||
class | exec | in | raise | |
continue | finally | is | return | |
def | for | lamda | try |