35

When considering design, in which cases does it make sense to use class versus dict? Pros & Cons would be useful too.

For example,

class AlbumState:
    """ AlbumState class, tracks photos shown, etc"""

    def __init__ (self, album):
        """ album for this object will track state"""
        self.album = album

        self.photos_shown = []
        self.photos_notshown = range(album.size())

versus

albumstate['album'] = album
albumstate['photos_shown'] = []
albumstate['photos_notshown'] = range(album.size())
Henry Gomersall
  • 8,434
  • 3
  • 31
  • 54
amitc
  • 365
  • 1
  • 4
  • 8
  • Related to [Python: Should I use a class or dictionary?](http://stackoverflow.com/questions/4045161/python-should-i-use-a-class-or-dictionary) and to [Convert Python dict to object?](http://stackoverflow.com/questions/1305532/convert-python-dict-to-object) – ChaimG Feb 19 '17 at 02:13

2 Answers2

29

I would say the first and most important criteria to distinguish whether to use a class or a dictionary is whether you just want to have some data storage or you also want to have some logic (i.e., methods).

If you only need to keep together several data, then a dictionary might be the way to go. On the other hand, if you need operations performed on that data, and there is a very tight relationship between the data and the operations (forming a kind of entity), then that really calls for using a class.

As @Ben is suggesting, you may start using just a dictionary when you have a bunch of related data, and if at some point your realize that you also need some logic for that data, you can turn the dictionary into a class.

You may also have a look at the Unified Modeling Language (UML) and its class diagrams to get a better feeling on how to use classes. If you are just doing some scripting or programming a small application you may not need to use UML, but if you are designing a bigger and more complex system, it can really help you to decide what and how many classes do you need beforehand.

betabandido
  • 18,946
  • 11
  • 62
  • 76
  • 1
    i'd only add, you can pretty easily take a dict and turn it into a class later on down the line if it turns out you thought you only wanted the data association, but subsequently need logic. Also, consider using defaultdict, since it looks like it will behave how you want your dicts behaving. – Ben Jun 19 '12 at 19:47
19

A dict can use any hashable value as a key, while a class instance needs to have strings that are legal identifiers as its "keys". So you can bundle together arbitrary data in a dict.

It's pretty common to use a trivial class as a more-convenient dict when your key values will all be valid identifier strings anyway:

class Box:
    pass

x = Box()

x.a = 0
x.b = 1

d = {}
d["a"] = 0   # "x.a" is easier to type than this
d["b"] = 1

print("Current value for 'a' is: {}".format(x.a))

As soon as you start to do proper object oriented design, and you have method functions that go along with the data, you want to have the data in a proper class so you can bundle the method functions in. It's legal to just have a dict and a handful of global functions that operate on it, but if they are all related, it just makes sense to bundle them up into a class.

And finally, note that a dict is a building-block that is used to implement a class. If you store values in a class, they are actually stored inside an internal dict and there is just some convenient syntax to access them.

print(x.a)  # prints 1

print(x.__dict__["a"])  # does exact same thing as previous line
steveha
  • 74,789
  • 21
  • 92
  • 117
  • Excellent answer. Especially the part: "...and you have method functions that go along with the data, you want to have the data in a proper class so you can bundle the method functions in. It's legal to just have a dict and a handful of global functions that operate on it, but if they are all related, it just makes sense to bundle them up into a `class`". That is one of the major selling points of OOP: Bundling methods and data so we don't have to have global functions that operate on loose variables. – Ugur Jun 26 '17 at 21:08