This notebook was put together by [Jake Vanderplas](http://www.vanderplas.com) for UW's [Astro 599](http://www.astro.washington.edu/users/vanderplas/Astr599_2014/) course. Source and license info is on [GitHub](https://github.com/jakevdp/2014_fall_ASTR599/).
In [1]:
%run talktools.py
(known as "Sequence objects")
list
: a mutable ordered array of datatuple
: an immutable ordered array of datadict
: an unordered mapping from keys to valuesset
: an unordered collection of unique elementsThe values in any of these collections can be arbitrary Python objects, and mixing content types is OK.
Note that strings are also sequence objects.
In [2]:
t = (12, -1)
print(type(t))
In [3]:
print(isinstance(t,tuple))
print(len(t))
Can mix types in a tuple
In [4]:
t = (12, "monty", True, -1.23e6)
print(t[1])
Indexing works the same way as for strings:
In [5]:
print(t[-1])
In [6]:
t[-2:] # get the last two elements, return as a tuple
Out[6]:
In [7]:
x = (True) ; print(type(x))
x = (True,) ; print(type(x))
In [8]:
x = ()
type(x), len(x)
Out[8]:
In [9]:
x = (,)
single-element tuples look like (element,)
tuples cannot be modified. but you can create new one with concatenation
In [10]:
t[2] = False
In [11]:
t[0:2], False, t[3:]
Out[11]:
In [12]:
## the above is
## not what we wanted... need to concatenate
t[0:2] + False + t[3:]
In [13]:
y = t[0:2] + (False,) + t[3:]
y
Out[13]:
In [14]:
t * 2
Out[14]:
Tuples are most commonly used in functions which return multiple arguments.
In [15]:
v = [1,2,3]
print(len(v))
print(type(v))
In [16]:
v[0:2]
Out[16]:
In [17]:
v = ["eggs", "spam", -1, ("monty","python"), [-1.2,-3.5]]
len(v)
Out[17]:
In [18]:
v[0] ="green egg"
v[1] += ",love it."
v[-1]
Out[18]:
In [19]:
v[-1][1] = None
print(v)
In [20]:
v = v[2:]
print(v)
In [21]:
# let's make a proto-array out of nested lists
vv = [ [1,2], [3,4] ]
In [22]:
len(vv)
Out[22]:
In [23]:
determinant = vv[0][0] * vv[1][1] - vv[0][1] * vv[1][0]
determinant
Out[23]:
the main point here: lists are mutable
In [24]:
v = [1,2,3]
v.append(4)
v.append([-5])
v
Out[24]:
Note: lists can be considered objects. Objects are collections of data and associated
methods. In the case of a list, append
is a method: it is a function
associated with the object.
In [25]:
v = v[:4]
w = ['elderberries', 'eggs']
v + w
Out[25]:
In [26]:
v
Out[26]:
In [27]:
v.extend(w)
v
Out[27]:
In [28]:
v.pop()
Out[28]:
In [29]:
v
Out[29]:
In [30]:
v.pop(0) ## pop the first element
Out[30]:
In [31]:
v
Out[31]:
In [32]:
v = [1, 3, 2, 3, 4]
v.sort()
v
Out[32]:
reverse
is a keyword of the .sort()
method
In [33]:
v.sort(reverse=True)
v
Out[33]:
.sort()
changes the the list in place
In [34]:
v.index(4) ## lookup the index of the entry 4
Out[34]:
In [35]:
v.index(3)
Out[35]:
In [36]:
v.count(3)
Out[36]:
In [37]:
v.insert(0, "it's full of stars")
v
Out[37]:
In [38]:
v.remove(1)
v
Out[38]:
In [ ]:
v.
Once you find a method, type (for example)
v.index?
and press shift-enter: you'll see the documentation of the method
In [40]:
v.index?
This is probably the most important thing you'll learn today
In [41]:
a = ['cat', 'window', 'defenestrate']
for x in a:
print(x, len(x))
In [42]:
for i,x in enumerate(a):
print(i, x, len(x))
In [43]:
for x in a:
print(x, end=' ')
The syntax for iteration is...
for variable_name in iterable:
# do something with variable_name
The range()
function creates a list of integers
(actually an iterator, but think of it as a list)
In [44]:
x = range(4)
x
Out[44]:
In [45]:
total = 0
for val in range(4):
total += val
print("By adding " + str(val) + \
" the total is now " + str(total))
range
([start
,] stop
[, step
])
→ list of integers
In [46]:
total = 0
for val in range(1, 10, 2):
total += val
print("By adding " + str(val) + \
" the total is now " + str(total))
Quick Exercise:
Write a loop over the words in this list and print the words longer than three characters in length:
In [47]:
L = ["Oh", "Say", "does", "that", "star",
"spangled", "banner", "yet", "wave"]
In [48]:
{1,2,3,"bingo"}
Out[48]:
In [49]:
type({1,2,3,"bingo"})
Out[49]:
In [50]:
type({})
Out[50]:
In [51]:
type(set())
Out[51]:
In [52]:
set("spamIam")
Out[52]:
sets have unique elements. They can be compared, differenced, unionized, etc.
In [53]:
a = set("sp")
b = set("am")
print(a, b)
In [54]:
c = set(["a","m"])
c == b
Out[54]:
In [55]:
"p" in a
Out[55]:
In [56]:
a | b
Out[56]:
In [57]:
# number 1... curly braces & colons
d = {"favorite cat": None,
"favorite spam": "all"}
d
Out[57]:
In [58]:
# number 2
d = dict(one = 1, two=2, cat='dog')
d
Out[58]:
In [59]:
# number 3 ... just start filling in items/keys
d = {} # empty dictionary
d['cat'] = 'dog'
d['one'] = 1
d['two'] = 2
d
Out[59]:
In [60]:
# number 4... start with a list of tuples
mylist = [("cat","dog"), ("one",1), ("two",2)]
dict(mylist)
Out[60]:
In [61]:
dict(mylist) == d
Out[61]:
In [62]:
d = {"favorite cat": None, "favorite spam": "all"}
In [63]:
d[0] # this breaks! Dictionaries have no order
In [64]:
d["favorite spam"]
Out[64]:
In [65]:
d[0] = "this is a zero"
d
Out[65]:
Dictionaries can contain dictionaries!
In [66]:
d = {'favorites': {'cat': None, 'spam': 'all'},\
'least favorite': {'cat': 'all', 'spam': None}}
d['least favorite']['cat']
Out[66]:
remember: the backslash ('\') allows you to across break lines. Not technically needed when defining a dictionary or list
In [67]:
# globals() and locals() store all global and local variables
globals().keys()
Out[67]:
In [68]:
L = []
for num in range(100):
if (num % 7 == 0) or (num % 11 == 0):
L.append(num)
print(L)
We can also do this with a list comprehension:
In [69]:
L = [num for num in range(100)\
if (num % 7 == 0) or (num % 11 == 0)]
print(L)
In [70]:
# Can also operate on each element:
L = [2 * num for num in range(100)\
if (num % 7 == 0) or (num % 11 == 0)]
print(L)
Example: Below is a list of information on 50 of the largest near-earth asteroids. Given this list of asteroid information, let's find all asteroids with semi-major axis within 0.2AU of earth, and with eccentricities less than 0.5
In [71]:
# Each element is (name, semi-major axis (AU), eccentricity, orbit class)
# source: http://ssd.jpl.nasa.gov/sbdb_query.cgi
Asteroids = [('Eros', 1.457916888347732, 0.2226769029627053, 'AMO'),
('Albert', 2.629584157344544, 0.551788195302116, 'AMO'),
('Alinda', 2.477642943521562, 0.5675993715753302, 'AMO'),
('Ganymed', 2.662242764279804, 0.5339300994578989, 'AMO'),
('Amor', 1.918987277620309, 0.4354863345648127, 'AMO'),
('Icarus', 1.077941311539208, 0.826950446001521, 'APO'),
('Betulia', 2.196489260519891, 0.4876246891992282, 'AMO'),
('Geographos', 1.245477192797457, 0.3355407124897842, 'APO'),
('Ivar', 1.862724540418448, 0.3968541470639658, 'AMO'),
('Toro', 1.367247622946547, 0.4358829575017499, 'APO'),
('Apollo', 1.470694262588244, 0.5598306817483757, 'APO'),
('Antinous', 2.258479598510079, 0.6070051516585434, 'APO'),
('Daedalus', 1.460912865705988, 0.6144629118218898, 'APO'),
('Cerberus', 1.079965807367047, 0.4668134997419173, 'APO'),
('Sisyphus', 1.893726635847921, 0.5383319204425762, 'APO'),
('Quetzalcoatl', 2.544270656955212, 0.5704591861565643, 'AMO'),
('Boreas', 2.271958775354725, 0.4499332278634067, 'AMO'),
('Cuyo', 2.150453953345012, 0.5041719257675564, 'AMO'),
('Anteros', 1.430262719980132, 0.2558054402785934, 'AMO'),
('Tezcatlipoca', 1.709753263222791, 0.3647772103513082, 'AMO'),
('Midas', 1.775954494579457, 0.6503697243919138, 'APO'),
('Baboquivari', 2.646202507670927, 0.5295611095751231, 'AMO'),
('Anza', 2.26415089613359, 0.5371603112900858, 'AMO'),
('Aten', 0.9668828078092987, 0.1827831025175614, 'ATE'),
('Bacchus', 1.078135348117527, 0.3495569270441645, 'APO'),
('Ra-Shalom', 0.8320425524852308, 0.4364726062545577, 'ATE'),
('Adonis', 1.874315684524321, 0.763949321566, 'APO'),
('Tantalus', 1.289997492877751, 0.2990853014998932, 'APO'),
('Aristaeus', 1.599511990737142, 0.5030618532252225, 'APO'),
('Oljato', 2.172056090036035, 0.7125729402616418, 'APO'),
('Pele', 2.291471988746353, 0.5115484924883255, 'AMO'),
('Hephaistos', 2.159619960333728, 0.8374146846143349, 'APO'),
('Orthos', 2.404988778495748, 0.6569133796135244, 'APO'),
('Hathor', 0.8442121506103012, 0.4498204013480316, 'ATE'),
('Beltrovata', 2.104690977122337, 0.413731105995413, 'AMO'),
('Seneca', 2.516402574514213, 0.5708728441169761, 'AMO'),
('Krok', 2.152545170235639, 0.4478259793515817, 'AMO'),
('Eger', 1.404478323548423, 0.3542971360331806, 'APO'),
('Florence', 1.768227407864309, 0.4227761019048867, 'AMO'),
('Nefertiti', 1.574493139339916, 0.283902719273878, 'AMO'),
('Phaethon', 1.271195939723604, 0.8898716672181355, 'APO'),
('Ul', 2.102493486378346, 0.3951143067760007, 'AMO'),
('Seleucus', 2.033331705805067, 0.4559159977082651, 'AMO'),
('McAuliffe', 1.878722427225527, 0.3691521497610656, 'AMO'),
('Syrinx', 2.469752836845105, 0.7441934504192601, 'APO'),
('Orpheus', 1.209727780883745, 0.3229034563257626, 'APO'),
('Khufu', 0.989473784873371, 0.468479627898914, 'ATE'),
('Verenia', 2.093231870619781, 0.4865133359612604, 'AMO'),
('"Don Quixote"', 4.221712367193639, 0.7130894892477316, 'AMO'),
('Mera', 1.644476057737928, 0.3201425983025733, 'AMO')]
orbit_class = {'AMO':'Amor', 'APO':'Apollo', 'ATE':'Aten'}
In [72]:
# first we'll build the list using loops.
L = []
for data in Asteroids:
name, a, e, t = data
if abs(a - 1) < 0.2 and e < 0.5:
L.append(name)
print(L)
In [73]:
# now with a list comprehension...
L = [name for (name, a, e, t) in Asteroids
if abs(a - 1) < 0.2 and e < 0.5]
print(L)
Here is how we could create a dictionary from the list
In [74]:
D = dict([(name, (a, e, t)) for (name, a, e, t) in Asteroids])
print(D['Eros'])
print(D['Amor'])
Using the above Asteroid list,
The output should be formatted like this:
Asteroid name a (AU) e class
-----------------------------------------
Eros 1.4578 0.2226 Amor
Albert 2.6292 0.5518 Amor
.
.
.
Bonus points if you can get the columns to line up nicely!