At my job, I had an API problem: I had a object property that could contain one or more strings. I assumed it would be a list, some of my users felt that
['value',] was harder to write than
'value'. I found myself making the same mistake. So, I solved the problem, then I took the rough class I wrote and polished it. It’s up on my github, at https://github.com/jjmojojjmojo/stringlist
So what is it?
It’s a class that tries to make a slick API when there can be one, or many values for a property. The class can be instantiated with either a single value or many. If you use many, it will act like a list. If you use a single value (a string), it will act like a string. If it’s a string, and you use the
.append() method, it becomes a list. Bam.
How would I use it?
class Thing(object): """ Arbitrary class representing a single thing with one or more roles. """ role = StringList() def __init__(self, role=None): self.role = role # initialize with a single string value obj = Thing('single role') # initialize with multiple string values obj = Thing(('one', 'two', 'three')) # set to a single string value obj.roles = 'new role' # set to many string values obj.roles = 'primary', 'secondary' # when it's a string, it works like a string obj = Thing('role1') # ROLE1 obj.roles = obj.upper() # convert to a list using .append() obj.roles.append('role2') # now its a list obj.roles == 'role2'
- The module sports 100% test coverage.
- There is a buildout in the repo. Just run
python bootstrap.py; bin/buildoutand then you can run the tests with
- It was originally developed to avoid
['h', 'e', 'l', 'l', 'o']mistakes when a single string was used instead of a list.
- This is the first time I’ve used descriptors in Python. Very cool.
- It would not have been possible without this marvelous post about Python’s magic methods (big thanks to Rafe Kettler).
- Some things were not as straight-forward as they could have been, given Python’s string implementation. Of special interest is the implementation of the
__iter__methods. In both cases, the base
strclass doesn’t have either method, so instead of doing the sane thing and proxying the call, I had to fall back to re-doing the operation in the method.