2009-11-29 2 views
1

Я работаю с библиотекой с открытым исходным кодом, и они определяют класс следующим образом:Каков предпочтительный метод преобразования свойств объекта в отсортированный список кортежей?

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 

мне нужно принять свойства (фиктивной, EC2 и т.д.) и конвертировать их в отсортированный список кортежей что бы выглядело примерно так:

[(0, 'DUMMY'), (1, 'EC2'), ...] 

Я хочу сортировать имя самого объекта недвижимости. Я придумал несколько способов решения этого, в том числе, после чего кажется как неэффективный способ справиться с этим:

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)) 

Это работает, но кажется, безвкусный и как там может быть лучше. Я также вижу недостатки в том, как я создаю список, делая if not k.startswith('__') - в основном, что если lib с открытым исходным кодом добавляет методы в класс Provider?

Просто найдите некоторые мнения и другие методы, которые могут работать лучше для этого.

+1

Зачем вам это нужно в первую очередь? – Randell

+1

Используйте 'if not k.startswith ('_')'. Это соглашение, что элементы, начинающиеся с '_', не являются общедоступными. – jfs

+0

Что вы на самом деле пытаетесь достичь здесь? Если вы хотите иметь контейнер для констант, вы можете также использовать словарь. Или просто используйте строки (например, «GOGRID»), так как это питонический способ справиться с такими вещами. (Строки интернированы, а многие из той же строки не попадают в память, поэтому они как-то похожи на символы lisp.) – bayer

ответ

6

Если вы ищете переменные класса, которые целочисленного типа, вы могли бы сделать это следующим образом:

import inspect 
PROVIDER_CHOICES = inspect.getmembers(Foo, lambda x: isinstance(x, int)) 

Отъезд inspect модуль для получения дополнительной информации.


Как и в сторону: вы можете использовать PROVIDER_CHOICES.sort(key=...) в последней строке, которая делает INPLACE рода.

Edit: getmembers возвращает отсортированный список, как указано в документации, так sorted ненужно (спасибо J.F. Sebastian)

+1

'inspect.getmembers()' уже возвращает список, отсортированный по имени. – jfs

+0

это замечательно. гораздо более элегантным и понятным. J.F. прав. Я удалил 'sorted()' wrapped вокруг 'inspect.getmembers()', и он отсортировался отлично. – richleland

0

Если вы беспокоитесь о методах и другие типы атрибутов просто фильтровать их тоже.

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)) 

Вам просто нужно запустить этот раз для каждого класса, о котором идет речь, поэтому скорость не должна быть проблемой для начала. Если вам действительно все равно, вы можете просто сохранить список в самом классе.

Смежные вопросы