Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

functional python: item vs attribute

Hi, In the Function Python Workhorses: Sorting video, there's a part at the end where Kenneth Love uses both itemgetter and attrgetter. I'm a bit confused as to why/how the two are used differently. Why is publish_date an item to be referenced while number_of_pages is an object attribute? Looking at the json file, it seems as though both publish_date and number_of_pages are written/stored similarly and should be called the same way. I tried flipping the keys (used attrgetter for publish_date and itemgetter for number_of_pages) but it didn't work. Could someone help me to understand why?

import json
from operator import attrgetter, itemgetter

class Book:
    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

    def __str__(self):
        return self.title

    def __repr__(self):
        return str(self)


def get_books(filename, raw=False):
    try:
        data = json.load(open(filename))
    except FileNotFoundError:
        return []
    else:
        if raw:
            return data['books']
        return [Book(**book) for book in data['books']]

BOOKS = get_books('books.json')
RAW_BOOKS = get_books('books.json', raw=True)

# pub_sort = sorted(RAW_BOOKS, key=itemgetter('publish_date'))
# print(pub_sort[0]['publish_date'], pub_sort[-1]['publish_date'])
pages_sort = sorted(BOOKS, key=attrgetter('number_of_pages'))
print(pages_sort[0].number_of_pages, pages_sort[-1].number_of_pages)

#important_list = [5, 3, 1, 2, 4]
#important_list.sort()  # Bad idea, sorts list in place
# sorted(important_list)  # Sorts a copy of the list

here's a couple of examples from the json file

{ "books" : [ { "number_of_pages" : 849,
        "price" : 13.550000000000001,
        "publish_date" : 2011,
        "subjects" : [ "Time travel",
            "Assassination"
          ],
        "title" : "11/22/63"
      },


      { "number_of_pages" : 732,
        "price" : 7.9900000000000002,
        "publish_date" : 1999,
        "subjects" : [ "Authors",
            "Custody of children",
            "Grandfathers",
            "Haunted houses",
            "Novelists",
            "Trials (Custody of children)",
            "Widowers",
            "Widows",
            "Writer's block"
          ],
        "title" : "Bag of bones"
      },

2 Answers

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,468 Points

The specifically difference between using attrgetter and itemgetter is the target object. Since BOOKS is an object with attributes, and RAW_BOOKS is a "container" (list, dict, set) filled with items, the choice becomes clearer.

because there's a difference between BOOKS and RAW_BOOKS. just caught that. sorry.