python image


What Makes Python So Great?

According to w3schools.com

  • Python was designed for readability, and has some similarities to the English language with influence from mathematics.
  • Python uses new lines to complete a command, as opposed to other programming languages which often use semicolons or parentheses.
  • Python relies on indentation, using whitespace, to define scope; such as the scope of loops, functions and classes. Other programming languages often use curly-brackets for this purpose.
  • Python has syntax that allows developers to write programs with fewer lines than some other programming languages.
  • Python runs on an interpreter system, meaning that code can be executed as soon as it is written. This means that prototyping can be very quick.

So What?

  • Python can be treated in a procedural way, an object-oriented way or a functional way.
  • Python can connect to database systems. It can also read and modify files.
  • Python can be used to handle big data and perform complex mathematics.

Python also has libraries that are invaluable in the field of Data Science such as:

python libraries


Now What?

Click here for a great Python cheatsheet that covers pretty much any basic thing you might want to know.

You might want to check and see what version of Python you are running by typing the following in your terminal:

python --version

You can also run the following right in your Jupyter Notebook:

In [1]:
!python --version
Python 3.7.4

len() and type() functions

len(sequence_object)

type(object)

I want to introduce two python functions nice and early because I will use them a lot! I can use the built-in function len() to return the number of elements in a sequence like a string or a list. I can use the built-in function type() to check my data type.


Data Types


Data Type Image


Numeric Types -> int, float

An int is a whole number and a float is a decimal number. Jumping ahead a bit, you will find out that missing values are also considered float types.

In [2]:
type(7)
Out[2]:
int
In [3]:
type(7.5)
Out[3]:
float
In [4]:
import numpy as np

type(np.NaN)
Out[4]:
float

Boolean Type -> bool

Boolean values, True and False, are not strings, so they do not go in quotation marks, and they are case sensitive. Rather they inform me if my expression or condition logic evaluates to True or False. It's common to hear that a value is truthy or falsy. You can also think of boolean values as binary integers in that True == 1 and False == 0.

In [5]:
# The comparison returns `False`, a bool value because the lengths are not the same.

len('violet') == len('blue')
Out[5]:
False
In [6]:
type(len('violet') == len('blue'))
Out[6]:
bool
In [7]:
False != True
Out[7]:
True
In [8]:
True == 1
Out[8]:
True
In [9]:
False == 0
Out[9]:
True

Sequence Types -> str, list, tuple, range

A Python String can be surrounded by single or double quotation marks. I can have an empty string with no characters or a string can contain multiple words, numbers, symbols, and whitespace characters. Click here to see what you can do with strings.

In [10]:
type('Python rocks!')
Out[10]:
str
In [11]:
type("a")
Out[11]:
str
In [12]:
type('')
Out[12]:
str

A Python list can contain elements of different data types and is a mutable object. Duplicate values are allowed. Notice the square brackets surrounding the elements. Click here to see what you can do with lists.

I can create a Python list in several different ways:

In [13]:
# I can create an empty list as simply as this with the list constructor...

new_empty_list = []

print(type(new_empty_list))
new_empty_list
<class 'list'>
Out[13]:
[]
In [14]:
# I can create a populated list from the very start; notice it can contain various data types.

mixed_list = [1, 3.5, 'apple']

print(type(mixed_list))
mixed_list
<class 'list'>
Out[14]:
[1, 3.5, 'apple']

A Python tuple is an ordered, immutable object. Duplicate values are allowed. Notice the parentheses surrounding the pair of elements.

In [15]:
type((1, 3))
Out[15]:
tuple
In [16]:
type(('red', 'blue', 'green'))
Out[16]:
tuple

A Python range() constructor creates a range object.

range(start, stop, step)

Range Image

If I pass only one integer as my argument, the start (inclusive) is 0 and stop (exclusive) 1 less than my argument. The step defaults to 1 if not specified.

In [17]:
range(6)
Out[17]:
range(0, 6)

I can loop through my range object like this... (more on loops later)

In [18]:
for i in range(6):
    print(i)
0
1
2
3
4
5

I can also wrap my range object in the built-in list() constructor to return a list of the integers specified by my range object.

In [19]:
list(range(6))
Out[19]:
[0, 1, 2, 3, 4, 5]

Here, I specify that the range starts at 0 and stops at 10 (exclusive) moving in steps of 2 instead of 1.

In [20]:
r = range(0,10,2)
r
Out[20]:
range(0, 10, 2)
In [21]:
evens_list = list(r)
evens_list
Out[21]:
[0, 2, 4, 6, 8]

Now I can pass this list to other functions like this...

In [22]:
# I can sum the integers in my list.

sum(evens_list)
Out[22]:
20
In [23]:
# I can return the number of elements in my list.

len(evens_list)
Out[23]:
5

Mapping Type -> dict

A Python dictionary object is made up key:value pairs separated by a comma. It is a mutable object that does not allow duplicates. Notice the curly brackets surrounding the key:value pairs.

I can create a Python dictionary in several different ways:

In [24]:
# I can create an empty dictionary as simply as this with the dictionary constructor...

new_empty_dictionary = {}

print(type(new_empty_dictionary))
new_empty_dictionary
<class 'dict'>
Out[24]:
{}
In [25]:
# I can create a populated dictionary from the very start; notice it can contain key/value pairs.

day_dict = {'weekday': 'Thursday', 'day': 20, 'month': 'October', 'year': 2020}

print(type(day_dict))
day_dict
<class 'dict'>
Out[25]:
{'weekday': 'Thursday', 'day': 20, 'month': 'October', 'year': 2020}

Dictionary indexing is a little different from other sequences like lists and tuples; I access values in a dictionary by passing the key into square brackets instead of an integer for the index location. I'll go into dictionary functionality more here.

In [26]:
day_dict['weekday']
Out[26]:
'Thursday'
In [27]:
day_dict['day']
Out[27]:
20

Set Type -> set

A Python set object is an unordered and unindexed collection that is immutable and contains only unique values. Notice the curly brackets. I've opted to focus on list and dictionary methods in this basic notebook, but here is a link to set methods for future use. They are quite useful when looking for differences or similarities between elements in different sequences.

In [28]:
# Here I use curly brackets to create a set.

a_set = {1, 1, 2, 5}
type(a_set)
Out[28]:
set

When I use the built-in len() function, I see that only the unique elements in the set are counted. This can come in very handy when checking for unique elements in a list.

In [29]:
# This tells me there are 3 unique elements in a_set.

len(a_set)
Out[29]:
3
In [30]:
# Here I use square brackets to create a list containing the same elements as in my set.

a_list = [1, 1, 2, 5]
len(a_list)
Out[30]:
4
In [31]:
# This list does not contain all unique elements.

len([1, 1, 2, 5]) == len({1, 1, 2, 5})
Out[31]:
False

Operators


This is just a quick reference for Python operators. I'll be using these in action throughout this and in all future notebooks.

Comparison Operators

Comparison Operator Image


Arithmetic Operators

Arithmetic Operators Image


Logic Operators

Logic Operator Image


Bitwise Operators

Bitwise Operators Image


String Operations


String Methods

There are a ton of useful built-in methods that can be accessed using dot notation with Python string variables. To check out some of these methods, let's create a variable that holds a string as an example. To check out way more, check the doc here.

In [32]:
a_string = 'I am a string!'
In [33]:
type(a_string)
Out[33]:
str

.lower(), .upper(), .capitalize(), .title(), swapcase()

These string methods transform the characters in my string to either lowercase or uppercase in various ways. Check out the examples below:

In [34]:
a_string.lower()
Out[34]:
'i am a string!'
In [35]:
a_string.upper()
Out[35]:
'I AM A STRING!'
In [36]:
a_string.capitalize()
Out[36]:
'I am a string!'
In [37]:
a_string.title()
Out[37]:
'I Am A String!'
In [38]:
a_string.swapcase()
Out[38]:
'i AM A STRING!'
In [39]:
# Using a string method doesn't mutate my original string; it returns a copy I can use or assign.

a_string
Out[39]:
'I am a string!'

.islower(), .isupper()

I can use these methods to return a bool value if all of the characters in my string are lowercase or uppercase.

In [40]:
# I can assign my string in all caps to a variable for further use.

caps = a_string.upper()
caps
Out[40]:
'I AM A STRING!'
In [41]:
# I can check my string for all upper- or all lowercase letters.

caps.isupper()
Out[41]:
True
In [42]:
caps.islower()
Out[42]:
False

.strip(), .replace()

These string methods are useful to perform a little string cleanup by removing any whitespace from the beginning or end of my string and replacing a string with another string.

# default for strip is to take out whitespace; `[chars]` is optional.

str.strip([chars])
str.lstrip([chars])
str.rstrip([chars])

# default replaces all occurences of the old with the new; this can be adjusted.

string.replace(old, new, [count=-1])
In [43]:
a_string = ' I am a string. I am a messy string! '
In [44]:
# Strip whitespace from beginning and end of string.

a_string.strip()
Out[44]:
'I am a string. I am a messy string!'
In [45]:
# Strip whitespace from beginning of string.

a_string.lstrip()
Out[45]:
'I am a string. I am a messy string! '
In [46]:
# Strip whitespace from end of string.

a_string.rstrip()
Out[46]:
' I am a string. I am a messy string!'
In [47]:
b_string = '!?I have junk at the front I don\'t need.'
In [48]:
# The default is whitespace, but I can strip out other characters as well.

b_string.strip('!?')
Out[48]:
"I have junk at the front I don't need."

In [49]:
a_string.replace('string', 'something')
Out[49]:
' I am a something. I am a messy something! '
In [50]:
# I can pass in a number of occurences to replace if I don't want to replace them all.

a_string.replace('string', 'something', 1)
Out[50]:
' I am a something. I am a messy string! '
In [51]:
# I can chain these methods together, too! I can replace and strip at the same time.

a_string.replace('string', 'something', 1).strip()
Out[51]:
'I am a something. I am a messy string!'

.isalnum(), .isalpha(), .isdigit(), .isspace()

These handy string methods return a bool value telling me if all of the characters in the string are either alphanumeric, alphabetic, digits, or tabs/spaces/newlines respectively.

In [52]:
# Define variables for use below

alpha = 'alphabetic'
alphanumeric = 'unit9'
digits = '210'
In [53]:
alpha.isalpha()
Out[53]:
True
In [54]:
alphanumeric.isalnum()
Out[54]:
True
In [55]:
digits.isdigit()
Out[55]:
True
In [56]:
digits.isspace()
Out[56]:
False

.split(), .partition(), .join()

I can split my string using a specific separator like a space or a hyphen and return the elements in a list (.split()) or tuple (.partition()), and I can join on a specific separator, too.

# I can split a string into a list; the default separator is a whitespace if none is passed. I can pass an integer along with a separator to control the number of splits, but this is also optional.

str.split(separator, maxsplit=int)

# I can split a string into a tuple containing three elements, 1-elements before value, 2-value, 3-elements after value.

str.partition(value)

# I can join all of the items in a sequence_of_strings (an iterable) and join them on the string_separator I specify.

'str_separator'.join(sequence_of_strings)
In [57]:
# Now I have a list of the elements in my string and can access them using indexing.

a_list = a_string.split()
a_list
Out[57]:
['I', 'am', 'a', 'string.', 'I', 'am', 'a', 'messy', 'string!']
In [58]:
a_list[-1]
Out[58]:
'string!'
In [59]:
a_list[0]
Out[59]:
'I'
In [60]:
# I can use partition to break my string on the separator I pass as an argument and index into the tuple.

a_tuple = 'Codeup rocks!'.partition(' ')
a_tuple
Out[60]:
('Codeup', ' ', 'rocks!')
In [61]:
# Now I can use indexing to access strings in my tuple.

a_tuple[0]
Out[61]:
'Codeup'
In [62]:
# I can join the elements of my list on a whitespace or some other separator, as well.

' '.join(a_list)
Out[62]:
'I am a string. I am a messy string!'
In [63]:
phone_string = '210-299-2080'
In [64]:
# I can split on a specific separator and even control how many times I split.

phone_string.split('-', maxsplit=1)
Out[64]:
['210', '299-2080']

.startswith(), .endswith()

I can return a bool value indicating if a string starts or ends with a substring I pass as an argument.

# I have to pass a value, but specifying the index position at which to start and end my search is optional.

str.startswith(value, start, end)

# The same applies here.

str.endswith(value, start, end)
In [65]:
e_string = 'automobile'
In [66]:
e_string.startswith('auto')
Out[66]:
True

.count()

I can count the number of occurences of a particular value in a string. The starting and ending index values are optional parameters that allow me more precision if I need it.

# I have to pass a value, but specifying the index position at which to start and end my search is optional.

str.count(value, start, end), where :
In [67]:
# There are two o characters in my e_string.

e_string.count('o')
Out[67]:
2

String Formatting

The print() function will display your value to your screen. I can format my output in several ways, a few of which I will demonstrate below.

f-strings allow me to print a string AND varibales by passing an f-string to my print function with variables inside of curly braces. Here is more on f-strings if interested.

In [68]:
a_num = '20'

print(f'The number {a_num} contains {len(a_num)} digits!')
The number 20 contains 2 digits!
In [69]:
name = 'Codeup'
company = 'Career Accelerator'

print(f'{name} is a {company}.')
Codeup is a Career Accelerator.

The .format() method is another way to combine strings and variables in a print statement.

In [70]:
cnt = 3
price = 1.99
total = cnt * price

print('I bought {} coffees at {} each for a total of {}.'.format(cnt, price, total))
I bought 3 coffees at 1.99 each for a total of 5.97.

The string modulo operator % offers a lot more string formatting options, but to keep this basic notebook basic, I'll just add a link to a very detailed look at options for when you hit a case that requires more than the above two options.


String Concatenation allows me to combine strings using the + operator. When a built-in operator or function displays different behaviors based on the type of object it is used with, this is called Operator Overloading.

In [71]:
greeting = 'Hi'
name = 'there!'

print(greeting + ' ' + name)
Hi there!

String Multiplication allows me to create a new string with the original string repeated n times by using the * operator. This is another example of Operator Overloading.

In [72]:
s = 'happy '
s * 5
Out[72]:
'happy happy happy happy happy '
In [73]:
s * 0
Out[73]:
''

Comments in this section? Sure, why not?!

In [74]:
# You can use a hashtag to add comments to your code.
In [75]:
'''
You can use triple quotes, single or double, 
to write multi-line comments or add docstrings
to functions, which we'll see in the next notebook.
'''
Out[75]:
"\nYou can use triple quotes, single or double, \nto write multi-line comments or add docstrings\nto functions, which we'll see in the next notebook.\n"

String Indexing & Slicing

Positive String Indexing

Python assigns a number to each character in a string, starting from 0 counting up to the last character in the string. We use these numbers to access specific characters in a string or elements in other sequences like lists, tuples, or sets.

string indexing image

Negative String Indexing

Python also allows us to reference characters in a string using negative indexing that assigns -1 to the last character in the string. Negative indexing is very useful when you don't know how many characters are in a string, but you want to grab the last one or two only. We will see this same indexing system when we dive into Python lists, too.

The Indexing Operator (square brackets) [] allow me to isolate a character in a string by passing in a number representing the index position of a specific character.

In [76]:
e_string
Out[76]:
'automobile'
In [77]:
# I can grab the first character in a string.

e_string[0]
Out[77]:
'a'
In [78]:
# I can grab the last character in a string.

e_string[-1]
Out[78]:
'e'

String Slicing

I can slice a string using the same bracket notation as above; slicing allows me to isolate multiple characters in a string.

str[start (inclusive): stop (exclusive): step]
In [79]:
# I can leave out the start index if I want to start from 0.

e_string[:4]
Out[79]:
'auto'
In [80]:
# I can leave out the column index if I want to end at the end or -1.

e_string[4:]
Out[80]:
'mobile'
In [81]:
# I can reverse my string by passing -1 as my step argument with default start and stop.

e_string[::-1]
Out[81]:
'elibomotua'

Handy Keywords

in, not in

These are two very useful membership operators used to verify if a string contains a certain substring or character. These will be useful with other sequence types, as well.

In [82]:
# Define variables for use below.

vowels = 'aeiou'
o_string = 'o'
p_string = 'P'
In [83]:
# I can use the .lower() method on my string to catch any capital letters in my string.

o_string.lower() in vowels
Out[83]:
True
In [84]:
p_string.lower() not in vowels
Out[84]:
True
In [85]:
# Print out the string stored in my `b_string` variable.

print(b_string)
!?I have junk at the front I don't need.
In [86]:
'junk' in b_string
Out[86]:
True

List Operations


List Methods

Like we saw with strings above, there are many useful built-in list methods that allow us to perform all types of manipulations on our list objects. We will look at a few very common methods below, but you can find many more here.

In [87]:
# I create my exmple list by surrounding a sequence of elements with square brackets.

color_list_original = ['red', 'yellow', 'violet', 'salmon']
In [88]:
# I can also use the `list()` constructor to create a list from another type of sequence.

clothes = ('shirt', 'pants', 'skirt', 'socks')
type(clothes)
Out[88]:
tuple
In [89]:
clothes_list_original = list(clothes)
type(clothes_list_original)
Out[89]:
list

I can use the .copy() method to create a copy of my sequence if I want to keep my original list intact because many of the list methods below perform in-place operations; this means they mutate my original list.

In [90]:
color_list = color_list_original.copy()
clothes_list = clothes_list_original.copy()

.append(), .extend()

I can add an item to the end of an existing list, and I can add a list to another list by joining them together respectively. These manipulations will mutate or change my original list.

list.append(element)

list.extend(iterable)
In [91]:
# I can add an item, shoes, to my clothes_list.

clothes_list.append('shoes')
In [92]:
# My original clothes_list now contains the appended item, shoes.

clothes_list
Out[92]:
['shirt', 'pants', 'skirt', 'socks', 'shoes']
In [93]:
color_list2 = ['indigo', 'orange']
In [94]:
# I can add the items in color_list2 to my original color_list.

color_list.extend(color_list2)
In [95]:
color_list
Out[95]:
['red', 'yellow', 'violet', 'salmon', 'indigo', 'orange']
In [96]:
# If I tried to use .append() to add my two lists together, this would happen...

clothes_list.append(color_list2)
In [97]:
# I get a nested list object. If you don't want this, use .extend().

clothes_list
Out[97]:
['shirt', 'pants', 'skirt', 'socks', 'shoes', ['indigo', 'orange']]
In [98]:
# Redefine lists to use in examples.

color_list = color_list_original.copy()
clothes_list = clothes_list_original.copy()
In [99]:
# I can also add two lists using the + operator and assign my new list to a variable.

new_list = color_list + clothes_list
new_list
Out[99]:
['red', 'yellow', 'violet', 'salmon', 'shirt', 'pants', 'skirt', 'socks']

.insert(), .remove(), .pop()

I can add an item to a list at a given position, remove the first item from my list that matches my specified value, and remove an item at a specific position from my list and return the item respectively. These manipulations will mutate or change my original list.

# I can insert an element into an existing list at a specified index position.

list.insert(index_position, element)

# I can remove the first occurrence of an element in a list.

list.remove(element)

# I can remove an element at a specified index position from a list and return that element.

list.pop(index_position)
In [100]:
# Redefine lists to use in examples.

color_list = color_list_original.copy()
clothes_list = clothes_list_original.copy()
In [101]:
# I pass the index of the element before which I want to insert my new element, 'aqua'.

color_list.insert(0, 'aqua')
In [102]:
# Now aqua is the first element in my list. If I used .append(), it would be the last.

color_list
Out[102]:
['aqua', 'red', 'yellow', 'violet', 'salmon']
In [103]:
# I will remove the item 'yellow' from my color_list

color_list.remove('yellow')
color_list
Out[103]:
['aqua', 'red', 'violet', 'salmon']
In [104]:
# I will remove and return the second item in my list, index 1, `red`.

color_list.pop(1)
Out[104]:
'red'
In [105]:
# Notice after I pop 'red', it is removed from my original list as well; it removes and returns the element.

color_list
Out[105]:
['aqua', 'violet', 'salmon']

.reverse(), .sort()

I can reverse the elements in my list or sort the elements alphabetically.

# I can perform a simple reverse of order on my original list.

list.reverse()

# I can sort my list in ascending/alphabetical order by default, passing no arguments to .sort(), or I can pass arguments for the reverse and key parameters to do way more complex sorts.

list.sort(reverse=True|False, key=function)
In [106]:
# Redefine lists to use in examples.

color_list = color_list_original.copy()
clothes_list = clothes_list_original.copy()
In [107]:
# I can reverse the elements in my original list.

color_list.reverse()
color_list
Out[107]:
['salmon', 'violet', 'yellow', 'red']
In [108]:
# I can sort the elements in my original list alphabetically by default.

clothes_list.sort()
clothes_list
Out[108]:
['pants', 'shirt', 'skirt', 'socks']
In [109]:
# I can sort in reverse alphabetical order, too!

clothes_list.sort(reverse=True)
clothes_list
Out[109]:
['socks', 'skirt', 'shirt', 'pants']
In [110]:
# I can pass a function, built-in or created, as a sorting key or criteria. Here I sort by string length!

color_list.sort(key=len)
color_list
Out[110]:
['red', 'salmon', 'violet', 'yellow']

List Indexing & Slicing

Once you understand positive and negative string indexing and slicing, you understand positive and negative list indexing. The difference is that the index number represents an element in your list (or tuple or set) instead of a character in your string.

List Index Image

In [111]:
color_list = color_list_original.copy()
color_list
Out[111]:
['red', 'yellow', 'violet', 'salmon']
In [112]:
# The default start is 0 and stop is exclusive, just like slicing strings.

color_list[:4]
Out[112]:
['red', 'yellow', 'violet', 'salmon']
In [113]:
# I can use indexing to reverse my list by selecting all elements ([::]) and passing a step of -1.

color_list[::-1]
Out[113]:
['salmon', 'violet', 'yellow', 'red']
In [114]:
# I can access values in a nested list, too.

nested_list = ['this', 'is', 'the', 'outer', 'list', ['and', 'inner', 'one']]
nested_list
Out[114]:
['this', 'is', 'the', 'outer', 'list', ['and', 'inner', 'one']]
In [115]:
# The 5th element in my list is a list, and I can grab elements from that list using the second [].

nested_list[5][1]
Out[115]:
'inner'

Dictionary Operations


Dictionary Methods

Again, dictionaries also have many useful built-in methods that allow us to perform all types of manipulations on our dictionary objects. We will look at a few very common methods below, but you can find more here.

Dictionary Image

In [116]:
# Define my example dictionary

day_dict = {'weekday': 'Thursday', 'day': 20, 'month': 'October', 'year': 2020}

.keys(), .values(), .items()

I can return a list of keys, values, or items (key/value pairs) from my dictionary object.

In [117]:
day_dict.keys()
Out[117]:
dict_keys(['weekday', 'day', 'month', 'year'])
In [118]:
day_dict.values()
Out[118]:
dict_values(['Thursday', 20, 'October', 2020])
In [119]:
day_dict.items()
Out[119]:
dict_items([('weekday', 'Thursday'), ('day', 20), ('month', 'October'), ('year', 2020)])

I can create a dictionary from two lists using an awesome function called zip(). This is just a preview of zip; we'll see more in zip and other cool python functions in a future notebook.

In [120]:
# Define the lists I want to be keys and values in my dictionary.

key_list = ['name', 'sign', 'age']
value_list = ['Betty', 'Aquarius', 1]
In [121]:
fam_dict = dict(zip(key_list, value_list))
fam_dict
Out[121]:
{'name': 'Betty', 'sign': 'Aquarius', 'age': 1}

Dictionary Indexing

I can access a value in my dictionary by passing the key into the indexing operator [].

In [122]:
fam_dict
Out[122]:
{'name': 'Betty', 'sign': 'Aquarius', 'age': 1}
In [123]:
fam_dict['name']
Out[123]:
'Betty'

I can loop through my dictionary using the .keys(), .values(), and .items() methods. (More on loops in a future notebook.)

In [124]:
# Print each key in my dictionary.

for key in fam_dict.keys():
    print(key)
name
sign
age
In [125]:
# Print each value in my dictionary.

for value in fam_dict.values():
    print(value)
Betty
Aquarius
1
In [126]:
# Print each item in my dictionary as a tuple.

for item in fam_dict.items():
    print(item)
('name', 'Betty')
('sign', 'Aquarius')
('age', 1)

Mixed Sequence Structures


I can dig into more complicated structures using indexing, as well. I have to be sure I use the appropriate indexing for each sequence. I'll demonstrate below:

In [127]:
# Create a list of four dictionaries.

fam_list = [{'name': 'Milla', 'sign': 'Virgo', 'age': 15},
            {'name': 'Birdie', 'sign': 'Gemini', 'age': 1},
            {'name': 'Starbuck', 'sign': 'Aries', 'age': 5},
            {'name': 'Faith', 'sign': 'Aquarius', 'age': 100}]

fam_list
Out[127]:
[{'name': 'Milla', 'sign': 'Virgo', 'age': 15},
 {'name': 'Birdie', 'sign': 'Gemini', 'age': 1},
 {'name': 'Starbuck', 'sign': 'Aries', 'age': 5},
 {'name': 'Faith', 'sign': 'Aquarius', 'age': 100}]
In [128]:
# Verifying the data type is a list.

print(type(fam_list))
<class 'list'>

Since this is a list, recall that I pass an integer representing an index position to the indexing operator like below. Revisit list indexing and slicing here.

list[0]

I can also slice my list to return segments of the sequence like this:

list[:2]
In [129]:
# This returns the first element in my list, which happens to be a dictionary.

fam_list[0]
Out[129]:
{'name': 'Milla', 'sign': 'Virgo', 'age': 15}
In [130]:
# This slice returns the first two elements in my list, which happen to be dictionaries.

fam_list[:2]
Out[130]:
[{'name': 'Milla', 'sign': 'Virgo', 'age': 15},
 {'name': 'Birdie', 'sign': 'Gemini', 'age': 1}]

What if I want to dig into the dictionaries in the list? I can do this by indexing into the list with the appropriate syntax and then the dictionary with the appropriate syntax.

Below I pass an iteger to the indexing operator to return the first element in my list. Since the first element in my list is a dictionary, I pass a key to the indexing operator to return the value that is paired with that key in the dictionary. Revisit dictionary indexing here.

In [131]:
# I return the first dictionary in my list and the value for the name key in my dictionary.

fam_list[0]['name']
Out[131]:
'Milla'
In [132]:
# I can return the value for the name key for each dictionary in my list like this:

for element in fam_list:
    print(element['name'])
Milla
Birdie
Starbuck
Faith

I can return the name of the oldest person/animal in my dictionary. This code utilizes for loops and an if statement to find the dictionary with the highest value for age and then print values from that dictionary. This is one way to get the values I want, but as will often be the case, there are many ways to accomplish my goal. I'll revisit this goal in a future notebook and explore other ways of getting this information.

In [133]:
# I iterate through my list adding the age from each dictionary to a new list, `ages`.

for element in fam_list:
    ages = []
    ages.append(element['age'])

# I use the max() function to return the max age in `ages` and assign that integer to `max_age`.

max_age = max(ages)

# I iterate through my list again and print different values if the age value matches `max_age`.

for element in fam_list:
    if element['age'] == max_age:
        print(f"The oldest person in the list is {element['name']}.")
        print(f"Her sign is {element['sign']}.")
The oldest person in the list is Faith.
Her sign is Aquarius.