Copying collections conveniently

In Python 3, lists, dicts and sets have a copy() method:

  1. >>> # Some things are easy to throw and catch...
  2. ... catchables = ["pillow", "frisbee", "ball"]
  3. >>> # And other things are just easy to throw:
  4. ... throwables = catchables.copy()
  5. >>> throwables.append("bowling ball")
  6. >>> throwables.append("sword")
  7. >>> throwables.append("grenade")
  8. >>> # Notice catchables isn't modified:
  9. ... catchables
  10. ['pillow', 'frisbee', 'ball']
  11. >>> throwables
  12. ['pillow', 'frisbee', 'ball', 'bowling ball', 'sword', 'grenade']

This is nice to have in Python, since it doesn't support "pass by value"; Python is only "pass by object reference". In other words, there's no way to pass an object to a function or method without risking it will modify that object. The only defense is to pass a copy instead.

I am hoping adding a "copy" method catches on, and becomes an increasing trend in all Python code. A quick way you can add this to your own classes:

  1. import copy
  2. class MyClass:
  3. # Insert your normal methods, and then:
  4. def copy(self):
  5. return copy.deepcopy(self)

I'll let you look up copy.deepcopy() yourself; it's in Python's standard library. But it's a good way to implement a copy() method for most classes.

As your class evolves, your copy() may need to do something different. Maybe your class keeps a database connection handle, for example, or some other attribute you shouldn't just blindly copy. The beauty of this approach is that you can start with the easy-to-remember default, to train people to rely on this method being there in your code. Then you change the copy() method to something more complex, if that's ever needed.

The key here is "training people to rely on your code". The more you can do this, the greater your impact on whatever project you're involved in... whatever team you're a part of.