I'm working with an open-source library and they define a class like so:
class Provider(object):
""" Defines for each of the supported providers """
DUMMY = 0
EC2 = 1
EC2_EU = 2
RACKSPACE = 3
SLICEHOST = 4
GOGRID = 5
VPSNET = 6
LINODE = 7
VCLOUD = 8
RIMUHOSTING = 9
I need to take the properties (DUMMY, EC2, etc.) and convert them to a sorted list of tuples that would look something like this:
[(0, 'DUMMY'), (1, 'EC2'), ...]
I want to sort on the name of the property itself. I've come up with a few ways to tackle this, including the following which seems like an inefficient way to handle this:
import operator
from libcloud.types import Provider
PROVIDER_CHOICES = [(v,k) for k, v in vars(Provider).items()
if not k.startswith('__')]
PROVIDER_CHOICES = sorted(PROVIDER_CHOICES, key=operator.itemgetter(1))
It works but seems inelegant and like there may be a better way. I also see flaws in the way I'm constructing the list by doing the if not k.startswith('__')
- mainly what if the open-source开发者_如何学C lib adds methods to the Provider class?
Just looking for some opinions and other techniques that may work better for this.
If you are looking for class variables that are of the type integer, you could do it like this:
import inspect
PROVIDER_CHOICES = inspect.getmembers(Foo, lambda x: isinstance(x, int))
Check out the inspect module for more information.
As an aside: you can use PROVIDER_CHOICES.sort(key=...)
in your last line, which does an inplace sort.
Edit: getmembers
returns a sorted list as stated in the documentation so sorted
is unnecessary (thanks J.F. Sebastian)
If you worry about methods and other types of attributes just filter them out too.
PROVIDER_CHOICES = [(v,k) for k, v in vars(Provider).iteritems()
if not k.startswith('_') and isinstance(v,int)]
PROVIDER_CHOICES.sort( key=itemgetter(1) )
You just have to run this once for every class in question, so speed shouldn't be a issue to begin with. If you really care, you can just store the list on the class itself.
精彩评论