% Lecture 2 Python % Jonah M. Duckles (jduckles@ou.edu)
Lists are created by placing list elements between []'s.
In [4]:
names = ['Tom', 'Dick', 'Hary']
In [9]:
names[0]
Out[9]:
In [14]:
names[1:3]
Out[14]:
slices use [start:end] notation where end is the first element NOT in the slice (a bit different than R's notation), also notice that the list index is based at 0, also a difference from R. More on slicing at Software Carpentry.
In [120]:
a = [1,2,3]
b = a
a[1] = 10
print(b)
Assignment = in python is just placing a pointer to a particular memory location. There is a very good chance that something else might change that memory location if the type is mutable (changeable).
In [5]:
for name in names:
print "Current name is " + name
Notice that we don't have to use explicit indexes in for loops.
This is because a list is considered to be an "iterable" in python. Iterables are just objects with a built in definition of what iteration over entails.
List objects have a series of methods on them useful for operating on lists
In [6]:
dir(names)
Out[6]:
We see that the object has a series of __xxx__ methods and a few named methods. Advanced: The __xxx__ methods are acutally revealing how that object responds to various other operators and functions. Iteration is actually handled by the __iter__ method.
The methods that don't begin with __ are the ones we want to look at.
Lets try one.
In [7]:
names.append('John')
In [8]:
names
Out[8]:
In [11]:
names.sort() # in place sort
In [12]:
names
Out[12]:
In [15]:
names.remove('John')
In [16]:
names
Out[16]:
In [18]:
print help(list.remove)
In [19]:
print help(list.sort)
In [74]:
def somefunction(someparam):
"""
A function that returns the parameter with some descriptive text
"""
return('You sent the parameter {}'.format(someparam))
In [75]:
help(somefunction)
In [77]:
somefunction('woooweee')
Out[77]:
In [23]:
names_tuple = ('Tom', 'Dick', 'Harry')
In [24]:
names_tuple
Out[24]:
Tuples just switch [] for (), but behavior is slightly different.
In [22]:
dir(names)
Out[22]:
In [27]:
names.index('Dick')
Out[27]:
In [43]:
bob1 = {'height': 76, 'first_name': 'Bob', 'last_name': 'Waldron', 'gender': 'M'}
dictionaries are created by placing {} and filling it with 'key': value pairs. The key must be a hashable, practically this means it should be a unique string for the dictionary { 'key1': value, 'key2': value2 }
In [33]:
bob2 = {'height': 76, 'height': 62 }
In [34]:
bob2
Out[34]:
Be carefull with dictionary keys. Duplicates keys will clober the previous value without warning.
In [19]:
print bob1.values() # Method to return a list of values
print bob1.keys() # Method to return list of keys
You can put a dictionary's values and keys back together using zip() and dict()
In [22]:
tmp = zip(bob1.keys(),bob1.values()) # putting a dictionary back together
print tmp
print dict(tmp)
We see that another way to create a dictionary is with a list of tuples which we run the dict() function on.
In [28]:
for k,v in bob1.items():
print "Key is: {} Value is: {}".format(k,v)
Items method just places tuples for each key/value pair into a list.
In [45]:
bob1.items()
Out[45]:
In [46]:
'Name: {first_name} {last_name} gender: {gender}'.format(first_name='Bob', last_name='Waldron', gender='M')
Out[46]:
In [52]:
template = 'Name: {first_name} {last_name} gender: {gender}'
template.format(**bob1) # Fill values with dictionary
Out[52]:
In [30]:
# Pretty numbers
population = 309000000
print '{:,}'.format(population)
More at: Python String Format
Dictionaries can have their own internal structure as well. It is handled as a dictionary inside of a dictionary.
In [125]:
client1 = {'name': "James Goodyear",
'address': { 'street': '100 Goodguy lane',
'city': 'Great Place',
'state': 'PA',
'zip': 15512
}
}
In [126]:
client2 = {'name': "Paul Gibson",
'address': { 'street': '204 Shady lane',
'city': 'Orlando',
'state': 'FL',
'zip': 68924
}
}
customers = [client1, client2]
In [128]:
print customers
Notice that hash-table collisions are not a problem across independent dictionaries.
In [129]:
client1['address']
Out[129]:
In [130]:
client1['address']['street']
Out[130]:
In [133]:
writer = open('example.txt', 'w')
writer.write('This is some text')
writer.write('Some more text')
writer.close()
In [135]:
reader = open('example.txt', 'r')
print reader.readline()
reader.close()
Ooops, we just appended the text together...we need to send line feeds.
In [136]:
writer = open('example.txt','w')
writer.write('This is some text\n')
writer.write('Some more text\n')
writer.close()
In [137]:
reader = open('example.txt', 'r')
for line in reader:
print line,
As part of the standard library there is a csv reader that should be used if you're reading/writing CSV data.
In [99]:
import csv
help(csv)
In [138]:
def add(a,b):
return a + b
add(1,10)
Out[138]:
Arguments are either positional or keyword arguments. Positional arguments are specified in the order they're declared in the function definition. keyword arguments are specified using keyword= notation.
Functions can have keyword parameters as well
In [87]:
def gravitationalforce(m1,m2,r,G=6.67384e-11):
"""
Compute gravitational force between two masses
using Newton's Law of Gravitation
F = G * (m1 * m2) / r^2
"""
return( G * (m1 * m2) / r**2 )
In [117]:
# Current gravitational force between Earth and Mars
mars_kg = 639e21
earth_kg = 5.972e24
mars_earth_102013 = 2.9772864e11
gravitationalforce(mars_kg,earth_kg,mars_earth_102013)
Out[117]:
We could provide an alternate Gravitational constant for an alternat universe if necessary. Not likely, but possible.
In [118]:
alternateG = 9.65e-11
gravitationalforce(mars_kg,earth_kg,mars_earth_102013,G=alternateG)
Out[118]:
You can also allow functions to take an arbitrary number of arguments and/or keyword arguments using a special syntax.
In [103]:
def passthrough(*args,**kwargs):
""" A function that takes an arbitrary number of arguments and kwargs and returns them """
return({'args':args, 'kwargs': kwargs })
In [102]:
passthrough(1,2,3,4,5,foo="something",bar="another thing")
Out[102]:
In [90]:
import numpy
values = [1,2,3]
array = numpy.array(values)
In [91]:
array
Out[91]:
Arrays are forced to have homogenious data types to improve performance and memory management.
In [95]:
values = [1,"2",3]
numpy.array(values)
Out[95]:
In [105]:
numpy.zeros((10,10))
Out[105]:
In [106]:
numpy.ones((10,5))
Out[106]:
In [108]:
numpy.identity(5)
Out[108]:
In [116]:
emptya = numpy.empty((4,4)) # Values are whatever was in memory location previously
print emptya
print emptya.shape
In [139]:
emptya.ravel() # unravel to 1-dimensional array
Out[139]: