+1 tag for Google+

Tuesday, 13 December 2016

Python Sorting Part 2: Classes and Attributes

Python Sorting with Classes and Attributes

# Here we define a class, containing student names
# each student contains an list attribute of varying from 1 to 7 in length
# populated by random integer values from 0 to 500

import random # imports the random module

# declares the class object
class myClass(object):
    def __init__(self, inputName):
        self.myName = inputName # creates a myName attribute
        # create a list of random length
        self.myList = [random.randint(0,500) \
                        for x in range(random.randint(1, 7))]
    def greet(self):
        # prints out name and list of values the instance holds
        print 'Hi I am {}, my list is {}'.format(self.myName, self.myList)

random.seed(0) # providing a seed to generate consistent random values
# Now we create instances of myClass for 5 students,
# and store the result as a list in studentNames
studentNames = ('tommy', 'sally', 'summer', 'jane', 'jonathan')
# For each item in studentNames, create a myClass instance
classList = [myClass(x) for x in studentNames]

# What kind of data does the list contain? Let's find out
print classList
# Result: [<__main__.myClass object at 0x0000000057D90470>,
# <__main__.myClass object at 0x0000000057D90320>,
# <__main__.myClass object at 0x0000000057D90240>,
# <__main__.myClass object at 0x0000000057D906A0>,
# <__main__.myClass object at 0x0000000057D906D8>] # 

# They are instances of myClass, that each hold name attribute values of
# 'tommy', 'sally', 'summer', 'jane', 'jonathan' in that order respectively
# They will also each have a list containing 1 to 7 items which are integers

# Loop through each myClass instance and call their greet() method
for person in classList:
# Result:
# Hi I am tommy, my list is [379, 210, 129, 256, 202, 392]
# Hi I am sally, my list is [238, 292, 454]
# Hi I am summer, my list is [141, 378, 309, 125]
# Hi I am jane, my list is [492, 405, 451, 155, 365, 450, 342]
# Hi I am jonathan, my list is [50, 217, 306, 457] #

# return just the names stored in myClass.myName attribute
[classList[x].myName for x in range(len(classList))]
# Result: ['tommy', 'sally', 'summer', 'jane', 'jonathan'] # 

# sorting the classes (and returning their myName values 
# by the length of their myName strings sorted([x.myName for x in classList], key=len)
# Result: ['jane', 'tommy', 'sally', 'summer', 'jonathan'] # 
# 'jane' is the shortest string and 'jonathan' is the longest string, correct ascending order

# return the name stored in myClass.myName attribute
# in the order of the length of the list contained in their myList attribute
y.myName for y in sorted([x for x in classList], 
  key=lambda(student): len(student.myList))]
# Result: ['sally', 'summer', 'jonathan', 'tommy', 'jane'] # 
# 'sally' has a myList attribute containing 3 items
# 'jane' has a myList attribute containing 7 items
# correct ascending order

# we can find out the sum of the items in each instance's list
[(x.myName, sum(x.myList)) for x in classList]
# Result: [('tommy', 1568),
 ('sally', 984),
 ('summer', 953),
 ('jane', 2660),

 ('jonathan', 1030)] # 

# Now we shall try to sort the class instances 
# ordered by the sum of their list items
[y.myName for y in sorted([x for x in classList], key=lambda(inst):sum(inst.myList))]

# Result: ['summer', 'sally', 'jonathan', 'tommy', 'jane'] # 
# 'summer' has a list with the sum of 953
# 'jane' has a list with the sum of 2660
# This is the correct ascending order according to each instance's sum

# When we enclose list comprehensions like that it is very confusing 
# and may be difficult to read.

# Here's that statement again, with colour coded blocks that we can examine in parts
[y.myName for y in sorted([x for x in classList]

# Let's break it down, starting from the inner most list comprehension:
[x for x in classList]
# This gives us the list of myClass instances in the order of the 
# studentNames list, which the class instances were created

# Expanding from that, we come to this statement
sorted([x for x in classList], key=lambda(inst):sum(inst.myList))
# We sort this list of class instances by using the key argument
# The lambda function returns to the sum of the instance's myList items
# the inst variable passed into the lambda function in this case will contain
# the myClass instance as the list of instances are passed in to be sorted

# With that sum's value as the key argument, the sorted([x for x...]) part of the statement 
# will return a list containing the class instances ordered by sum of the list's items

# Finally, the outermost list comprehension
[y.myName for y in sorted([x for x...], key=lambda...)]
# This simply take the already ordered list of class instances 
# (ordered by the sum of each instance's list items)
# and return the myName attribute

No comments:

Post a Comment