In [2]:
def stack_create():
    return []
In [3]:
s = stack_create()
In [4]:
type(s)
Out[4]:
list

Defining a new class

In [5]:
a = dict()
In [6]:
print(a)
{}
In [7]:
b = dict([("foo", 42), ("bar", 37)])
In [8]:
print(b)
{'bar': 37, 'foo': 42}
In [9]:
c = dict(b)
In [10]:
print(c)
{'bar': 37, 'foo': 42}

Constructor and attributes

In [11]:
class Point:
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
In [12]:
p1 = Point(42,37)
In [13]:
p2 = Point(0,0)
In [14]:
p3 = Point(-3,4)
In [15]:
p1.x
Out[15]:
42
In [16]:
p1.y
Out[16]:
37
In [17]:
p2.x
Out[17]:
0
In [18]:
p2.y
Out[18]:
0

Methods

In [19]:
d1 = dict( [("foo", 42), ("bar", 37)] )
d2 = dict( [("foo", 100), ("BAZ", 45)] )
In [20]:
print(d1)
{'bar': 37, 'foo': 42}
In [21]:
print(d2)
{'BAZ': 45, 'foo': 100}
In [22]:
d1.get("foo", "NOPE")
Out[22]:
42
In [23]:
d2.get("foo", "NOPE")
Out[23]:
100
In [24]:
d1.get("bar", "NOPE")
Out[24]:
37
In [25]:
d2.get("baz", "NOPE")
Out[25]:
'NOPE'
In [26]:
class Point:
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def distance_to_origin(self):
        return (self.x**2 + self.y**2)**0.5
In [27]:
p1 = Point(3, 4)
In [28]:
p1.distance_to_origin()
Out[28]:
5.0
In [29]:
p2 = Point(0, 0)
In [30]:
p2.distance_to_origin()
Out[30]:
0.0
In [31]:
p3 = Point(1, 1)
In [32]:
p3.distance_to_origin()
Out[32]:
1.4142135623730951

Stack class

In [33]:
class Stack:
    
    def __init__(self):
        self.lst = []
In [34]:
class Stack:
    
    def __init__(self):
        self.lst = []
        
    def push(self, value):
        self.lst.append(value)
        
    def pop(self):
        value = self.lst.pop()
        return value
    
    def peek(self):
        return self.lst[-1]
    
    def is_empty(self):
        return len(self.lst) == 0
In [35]:
s = Stack()
s.push(42)
s.push(37)
s.push(101)
s.push(53)
In [36]:
print(s.lst)
[42, 37, 101, 53]
In [37]:
s.pop()
Out[37]:
53
In [38]:
print(s.lst)
[42, 37, 101]

Private attributes

In [39]:
s.lst[1] = "FOOBAR"
In [40]:
print(s.lst)
[42, 'FOOBAR', 101]
In [41]:
class Stack:
    
    def __init__(self):
        self.__lst = []
        
    def push(self, value):
        self.__lst.append(value)
        
    def pop(self):
        value = self.__lst.pop()
        return value
    
    def peek(self):
        return self.__lst[-1]
    
    def is_empty(self):
        return len(self.__lst) == 0
In [42]:
s = Stack()
s.push(42)
s.push(37)
s.push(101)
s.push(53)
s.push(76)
In [43]:
s.pop()
Out[43]:
76
In [44]:
s.is_empty()
Out[44]:
False
In [45]:
print(s.__lst)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-45-7daa4c024a90> in <module>
----> 1 print(s.__lst)

AttributeError: 'Stack' object has no attribute '__lst'

Dunder methods

In [46]:
print(s)
<__main__.Stack object at 0x7f70545bc4a8>
In [47]:
class Stack:
    
    def __init__(self):
        self.__lst = []
        
    def push(self, value):
        self.__lst.append(value)
        
    def pop(self):
        value = self.__lst.pop()
        return value
    
    def peek(self):
        return self.__lst[-1]
    
    def is_empty(self):
        return len(self.__lst) == 0
    
    def __repr__(self):
        return "MY STACK"
In [48]:
s = Stack()
s.push(42)
s.push(37)
s.push(101)
s.push(53)
s.push(76)
In [49]:
print(s)
MY STACK
In [50]:
class Stack:
    
    def __init__(self):
        self.__lst = []
        
    def push(self, value):
        self.__lst.append(value)
        
    def pop(self):
        value = self.__lst.pop()
        return value
    
    def peek(self):
        return self.__lst[-1]
    
    def is_empty(self):
        return len(self.__lst) == 0
    
    def __repr__(self):
        return "STACK: " + ", ".join(str(v) for v in self.__lst) + " (top)"
In [51]:
s = Stack()
s.push(42)
s.push(37)
s.push(101)
s.push(53)
s.push(76)
In [52]:
print(s)
STACK: 42, 37, 101, 53, 76 (top)
In [53]:
s1 = Stack()
s1.push(42)
s1.push(37)

s2 = Stack()
s2.push(42)
s2.push(37)
In [54]:
s1 == s2
Out[54]:
False
In [55]:
class Stack:
    
    def __init__(self):
        self.__lst = []
        
    def push(self, value):
        self.__lst.append(value)
        
    def pop(self):
        value = self.__lst.pop()
        return value
    
    def peek(self):
        return self.__lst[-1]
    
    def is_empty(self):
        return len(self.__lst) == 0
    
    def __repr__(self):
        return "STACK: " + ", ".join(str(v) for v in self.__lst) + " (top)"
    
    def __eq__(self, other):
        return self.__lst == other.__lst
In [56]:
s1 = Stack()
s1.push(42)
s1.push(37)

s2 = Stack()
s2.push(42)
s2.push(37)

s3 = Stack()
s3.push(100)
In [57]:
s1 == s2
Out[57]:
True
In [58]:
s1 == s3
Out[58]:
False

OO Modeling

In [62]:
d1 = {"name": "Sam Q. Student", "majors": ["Computer Science"], "year": 2}
d2 = {"name": "Cris T. Student", "majors": ["Economics"], "year": 1}
d3 = {"name": "Ari F. Student", "majors": ["Mathematics", "Computer Science"], "year": 4}

dict_students = [d1, d2, d3]
In [60]:
class Student:
    
    def __init__(self, name, majors, year):
        self.name = name
        self.majors = majors
        self.year = year
In [63]:
s1 = Student("Sam Q. Student", ["Computer Science"], 2)
s2 = Student("Cris T. Student", ["Economics"], 1)
s3 = Student("Ari F. Student", ["Mathematics", "Computer Science"], 4)

students = [s1, s2, s3]
In [69]:
class Student:
    
    def __init__(self, name, majors, year):
        self.name = name
        self.majors = majors
        self.year = year
        
    def num_majors(self):
        return len(self.majors)
    
    def __repr__(self):
        return "Student: {}".format(self.name)
In [70]:
# Without objects

d1 = {"name": "Sam Q. Student", "majors": ["Computer Science"], "year": 2}
d2 = {"name": "Cris T. Student", "majors": ["Economics"], "year": 1}
d3 = {"name": "Ari F. Student", "majors": ["Mathematics", "Computer Science"], "year": 4}

dict_students = [d1, d2, d3]

for s in dict_students:
    print("Student: {}".format(s["name"]))
    print("Number of majors:", len(s["majors"]))
    print()
Student: Sam Q. Student
Number of majors: 1

Student: Cris T. Student
Number of majors: 1

Student: Ari F. Student
Number of majors: 2

In [72]:
# With objects

s1 = Student("Sam Q. Student", ["Computer Science"], 2)
s2 = Student("Cris T. Student", ["Economics"], 1)
s3 = Student("Ari F. Student", ["Mathematics", "Computer Science"], 4)

students = [s1, s2, s3]

for s in students:
    print(s)
    print("Number of majors:", s.num_majors())
    print()
Student: Sam Q. Student
Number of majors: 1

Student: Cris T. Student
Number of majors: 1

Student: Ari F. Student
Number of majors: 2

In [73]:
d4 = {"name": "Alex D. Student", "majors": ["Computer Science"], "year": -3, "capacity": "4GB"}
In [80]:
class Student:
    
    def __init__(self, name, majors, year):
        assert isinstance(name, str), "name must be a string"
        assert isinstance(majors, list) and all([isinstance(major, str) for major in majors]) ,\
               "majors must be a list of strings"
        assert 1 <= year <= 4, "year must be between 1 and 4"
        
        self.name = name
        self.majors = majors
        self.year = year
        
    def num_majors(self):
        return len(self.majors)
    
    def __repr__(self):
        return "Student: {}".format(self.name)
In [81]:
Student("Alex D. Student", ["Computer Science"], -3)
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-81-c8306db509b6> in <module>
----> 1 Student("Alex D. Student", ["Computer Science"], -3)

<ipython-input-80-44d8f6312004> in __init__(self, name, majors, year)
      5         assert isinstance(majors, list) and all([isinstance(major, str) for major in majors]) ,\
      6                "majors must be a list of strings"
----> 7         assert 1 <= year <= 4, "year must be between 1 and 4"
      8 
      9         self.name = name

AssertionError: year must be between 1 and 4
In [82]:
Student("Alex D. Student", ["Computer Science"], 1, "4GB")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-82-620ad8766c8c> in <module>
----> 1 Student("Alex D. Student", ["Computer Science"], 1, "4GB")

TypeError: __init__() takes 4 positional arguments but 5 were given
In [83]:
Student("Alex D. Student", ["Computer Science"], 1, capacity="4GB")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-83-83bfbddccca0> in <module>
----> 1 Student("Alex D. Student", ["Computer Science"], 1, capacity="4GB")

TypeError: __init__() got an unexpected keyword argument 'capacity'
In [84]:
Student(57.0, ["Computer Science"], 1)
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-84-f8f5fd1ce467> in <module>
----> 1 Student(57.0, ["Computer Science"], 1)

<ipython-input-80-44d8f6312004> in __init__(self, name, majors, year)
      2 
      3     def __init__(self, name, majors, year):
----> 4         assert isinstance(name, str), "name must be a string"
      5         assert isinstance(majors, list) and all([isinstance(major, str) for major in majors]) ,\
      6                "majors must be a list of strings"

AssertionError: name must be a string
In [86]:
Student("Alex D. Student", [1,2,3], 1)
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-86-51b5308fc6ea> in <module>
----> 1 Student("Alex D. Student", [1,2,3], 1)

<ipython-input-80-44d8f6312004> in __init__(self, name, majors, year)
      4         assert isinstance(name, str), "name must be a string"
      5         assert isinstance(majors, list) and all([isinstance(major, str) for major in majors]) ,\
----> 6                "majors must be a list of strings"
      7         assert 1 <= year <= 4, "year must be between 1 and 4"
      8 

AssertionError: majors must be a list of strings
In [87]:
# Printing the number of majors with the original implementation of Student.
# Assertions ommitted for clarity

class Student:
    
    def __init__(self, name, majors, year):        
        self.name = name
        self.majors = majors
        self.year = year
        
    def num_majors(self):
        return len(self.majors)
    
    def __repr__(self):
        return "Student: {}".format(self.name)
    
s1 = Student("Sam Q. Student", ["Computer Science"], 2)
s2 = Student("Cris T. Student", ["Economics"], 1)
s3 = Student("Ari F. Student", ["Mathematics", "Computer Science"], 4)

students = [s1, s2, s3]

for s in students:
    print(s)
    print("Number of majors:", s.num_majors())
    print()    
In [90]:
# We switch to an internal representation that separates the primary major
# from the rest of the majors. The code that prints out the majors continues
# working without any modifications.

class Student:
    
    def __init__(self, name, majors, year):        
        self.name = name
        self.primary_major = majors[0]
        self.secondary_majors = majors[1:]
        self.year = year
        
    def num_majors(self):
        return 1 + len(self.secondary_majors)
    
    def __repr__(self):
        return "Student: {}".format(self.name)
    
s1 = Student("Sam Q. Student", ["Computer Science"], 2)
s2 = Student("Cris T. Student", ["Economics"], 1)
s3 = Student("Ari F. Student", ["Mathematics", "Computer Science"], 4)

students = [s1, s2, s3]

for s in students:
    print(s)
    print("Number of majors:", s.num_majors())
    print()    
Student: Sam Q. Student
Number of majors: 1

Student: Cris T. Student
Number of majors: 1

Student: Ari F. Student
Number of majors: 2

The Divvy Example

In [96]:
import csv
In [92]:
stations = []

with open("data/divvy_2013_stations.csv") as f:
    reader = csv.DictReader(f)
    
    for row in reader:
        stations.append(row)
In [93]:
len(stations)
Out[93]:
300
In [94]:
stations[0]
Out[94]:
{'dpcapacity': '19',
 'id': '5',
 'landmark': '30',
 'latitude': '41.87395806',
 'longitude': '-87.62773949',
 'name': 'State St & Harrison St',
 'online date': '6/28/2013'}
In [95]:
trips = []

with open("data/divvy_2013_trips_tiny.csv") as f:
    reader = csv.DictReader(f)
    
    for row in reader:
        trips.append(row)
In [96]:
len(trips)
Out[96]:
100
In [97]:
trips[0]
Out[97]:
{'bikeid': '480',
 'birthday': '',
 'from_station_id': '85',
 'from_station_name': 'Michigan Ave & Oak St',
 'gender': '',
 'starttime': '2013-06-27 12:11',
 'stoptime': '2013-06-27 12:16',
 'to_station_id': '28',
 'to_station_name': 'Larrabee St & Menomonee St',
 'trip_id': '4118',
 'tripduration': '316',
 'usertype': 'Customer'}
In [178]:
class DivvyStation(object):

    def __init__(self, station_id, name, latitude, longitude,
                 dpcapacity, landmark, online_date):

        self.station_id = station_id
        self.name = name
        self.latitude = latitude
        self.longitude = longitude
        self.dpcapacity = dpcapacity
        self.landmark = landmark
        self.online_date = online_date
        
    def __repr__(self):
        return "<DivvyStation object, station_id={}, name='{}'>".format(self.station_id, self.name)
In [179]:
s25 = DivvyStation(25, "Michigan Ave & Pearson St", 41.89766, -87.62351, 23, 34, "6/28/2013")
s44 = DivvyStation(44, "State St & Randolph St", 41.8847302, -87.62773357, 27, 2, "6/28/2013")
s52 = DivvyStation(52, "Michigan Ave & Lake St", 41.88605812, -87.62428934, 23, 43, "6/28/2013")
In [180]:
s25
Out[180]:
<DivvyStation object, station_id=25, name='Michigan Ave & Pearson St'>
In [181]:
[s25, s44, s52]
Out[181]:
[<DivvyStation object, station_id=25, name='Michigan Ave & Pearson St'>,
 <DivvyStation object, station_id=44, name='State St & Randolph St'>,
 <DivvyStation object, station_id=52, name='Michigan Ave & Lake St'>]
In [182]:
print("Destination:", s25)
Destination: <DivvyStation object, station_id=25, name='Michigan Ave & Pearson St'>
In [183]:
class DivvyStation(object):

    def __init__(self, station_id, name, latitude, longitude,
                 dpcapacity, landmark, online_date):

        self.station_id = station_id
        self.name = name
        self.latitude = latitude
        self.longitude = longitude
        self.dpcapacity = dpcapacity
        self.landmark = landmark
        self.online_date = online_date
        
    def __repr__(self):
        return "<DivvyStation object, station_id={}, name='{}'>".format(self.station_id, self.name)
    
    def __str__(self):
        return "Divvy Station #{} ({})".format(self.station_id, self.name)
In [184]:
s25 = DivvyStation(25, "Michigan Ave & Pearson St", 41.89766, -87.62351, 23, 34, "6/28/2013")
s44 = DivvyStation(44, "State St & Randolph St", 41.8847302, -87.62773357, 27, 2, "6/28/2013")
s52 = DivvyStation(52, "Michigan Ave & Lake St", 41.88605812, -87.62428934, 23, 43, "6/28/2013")

stations = [s25, s44, s52]
In [185]:
s25
Out[185]:
<DivvyStation object, station_id=25, name='Michigan Ave & Pearson St'>
In [186]:
print("Destination:", s25)
Destination: Divvy Station #25 (Michigan Ave & Pearson St)
In [188]:
class DivvyTrip(object):
    def __init__(self, trip_id, starttime, stoptime, bikeid,
                 tripduration, from_station_id, from_station_name,
                 to_station_id, to_station_name,
                 usertype, gender, birthyear):
        self.trip_id = trip_id
        self.starttime = starttime
        self.stoptime = stoptime
        self.bikeid = bikeid
        self.tripduration = tripduration
        self.from_station_id = from_station_id
        self.from_station_name = from_station_name
        self.to_station_id = to_station_id
        self.to_station_name = to_station_name        
        self.usertype = usertype
        self.gender = gender
        self.birthyear = birthyear
        
    def __repr__(self):
        return "<DivvyTrip object, trip_id={}, from_station={}, to_station={}>".format(
                self.trip_id, self.from_station_id, self.to_station_id)
    
    def __str__(self):
        return "Divvy Trip #{} from {} to {}".format(self.trip_id, self.from_station_id, self.to_station_id)        
In [192]:
class DivvyTrip(object):
    def __init__(self, trip_id, starttime, stoptime, bikeid,
                 tripduration, from_station, to_station,
                 usertype, gender, birthyear):
        self.trip_id = trip_id
        self.starttime = starttime
        self.stoptime = stoptime
        self.bikeid = bikeid
        self.tripduration = tripduration
        self.from_station = from_station
        self.to_station = to_station
        self.usertype = usertype
        self.gender = gender
        self.birthyear = birthyear
        
    def __repr__(self):
        return "<DivvyTrip object, trip_id={}, from_station={}, to_station={}>".format(
                self.trip_id, self.from_station.station_id, self.to_station.station_id)
    
    def __str__(self):
        return "Divvy Trip #{} from {} to {}".format(self.trip_id, self.from_station.name, self.to_station.name)         
In [200]:
trip5433 = DivvyTrip(5433,   "2013-06-28 10:43", "2013-06-28 11:03", 218, 1214,
                     s25, s44, "Customer", None, None)
trip4666 = DivvyTrip(4666,   "2013-06-27 20:33", "2013-06-27 21:22", 242, 2936,
                     s44, s52, "Customer", None, None)
trip11236 = DivvyTrip(11236, "2013-06-30 15:41", "2013-06-30 15:58", 906, 1023,
                      s25, s44, "Customer", None, None)
trip4646 = DivvyTrip(4646,   "2013-06-27 20:22", "2013-06-27 20:39", 477, 996,
                     s52, s52, "Customer", None, None)
trip13805 = DivvyTrip(13805, "2013-07-01 13:21", "2013-07-01 13:35", 469, 858,
                      s44, s25, "Customer", None, None)

trips = [trip5433, trip4666, trip11236, trip4646, trip13805]
In [195]:
trip5433.to_station
Out[195]:
<DivvyStation object, station_id=44, name='State St & Randolph St'>
In [196]:
trip5433.from_station
Out[196]:
<DivvyStation object, station_id=25, name='Michigan Ave & Pearson St'>
In [197]:
trip5433.from_station.name
Out[197]:
'Michigan Ave & Pearson St'
In [198]:
trip5433.from_station.longitude
Out[198]:
-87.62351
In [199]:
trip5433.from_station.latitude
Out[199]:
41.89766
In [226]:
import math

class DivvyStation(object):

    def __init__(self, station_id, name, latitude, longitude,
                 dpcapacity, landmark, online_date):

        self.station_id = station_id
        self.name = name
        self.latitude = latitude
        self.longitude = longitude
        self.dpcapacity = dpcapacity
        self.landmark = landmark
        self.online_date = online_date
        
    def __repr__(self):
        return "<DivvyStation object, station_id={}, name='{}'>".format(self.station_id, self.name)
    
    def __str__(self):
        return "Divvy Station #{} ({})".format(self.station_id, self.name)

    def distance_to(self, other):
        diff_latitude = math.radians(other.latitude - self.latitude)
        diff_longitude = math.radians(other.longitude - self.longitude)

        a = math.sin(diff_latitude/2) * math.sin(diff_latitude/2) + \
            math.cos(math.radians(self.latitude)) * \
            math.cos(math.radians(other.latitude)) * \
            math.sin(diff_longitude/2) * math.sin(diff_longitude/2)
        d = 2 * math.asin(math.sqrt(a))

        return 6371000.0 * d
In [229]:
class DivvyTrip(object):
    def __init__(self, trip_id, starttime, stoptime, bikeid,
                 tripduration, from_station, to_station,
                 usertype, gender, birthyear):
        self.trip_id = trip_id
        self.starttime = starttime
        self.stoptime = stoptime
        self.bikeid = bikeid
        self.tripduration = tripduration
        self.from_station = from_station
        self.to_station = to_station
        self.usertype = usertype
        self.gender = gender
        self.birthyear = birthyear
        
    def __repr__(self):
        return "<DivvyTrip object, trip_id={}, from_station={}, to_station={}>".format(
                self.trip_id, self.from_station.station_id, self.to_station.station_id)
    
    def __str__(self):
        return "Divvy Trip #{} from {} to {}".format(self.trip_id, self.from_station.name, self.to_station.name)  
    
    def get_distance(self):
        return self.from_station.distance_to(self.to_station)
In [227]:
s25 = DivvyStation(25, "Michigan Ave & Pearson St", 41.89766, -87.62351, 23, 34, "6/28/2013")
s44 = DivvyStation(44, "State St & Randolph St", 41.8847302, -87.62773357, 27, 2, "6/28/2013")
s52 = DivvyStation(52, "Michigan Ave & Lake St", 41.88605812, -87.62428934, 23, 43, "6/28/2013")

stations = [s25, s44, s52]

trip5433 = DivvyTrip(5433,   "2013-06-28 10:43", "2013-06-28 11:03", 218, 1214,
                     s25, s44, "Customer", None, None)
trip4666 = DivvyTrip(4666,   "2013-06-27 20:33", "2013-06-27 21:22", 242, 2936,
                     s44, s52, "Customer", None, None)
trip11236 = DivvyTrip(11236, "2013-06-30 15:41", "2013-06-30 15:58", 906, 1023,
                      s25, s44, "Customer", None, None)
trip4646 = DivvyTrip(4646,   "2013-06-27 20:22", "2013-06-27 20:39", 477, 996,
                     s52, s52, "Customer", None, None)
trip13805 = DivvyTrip(13805, "2013-07-01 13:21", "2013-07-01 13:35", 469, 858,
                      s44, s25, "Customer", None, None)

trips = [trip5433, trip4666, trip11236, trip4646, trip13805]
In [221]:
total_distance = 0
for trip in trips:
    total_distance = trip.get_distance()
In [230]:
total_distance
Out[230]:
1479.6238912792467
In [224]:
total_duration = 0
for trip in trips:
    total_duration = trip.tripduration
In [225]:
total_duration
Out[225]:
858