Питонский перечисляемый список с поиском атрибутов и список значений

#python

Вопрос:

Распространенная идиома, которую я использую, звучит примерно так: (кстати, итератор не работает):

 SUMMARY = 'summary'
REPORT = 'report'

class PDF_TYPES:
    summary = SUMMARY
    report = REPORT

    class __metaclass__(type):
        def __iter__(self):
            return iter(list(self.summary, self.report))
 

Во-первых, это много шаблонов для 2 значений.

Я хотел бы определить некоторые константы в списке и иметь возможность:

  1. Обращайтесь к ним индивидуально, например REPORT , как указано выше
  2. Импортируйте весь список из другого модуля и обратитесь к ним как PDF_TYPES.report к etc. Словарь был бы import PDF_TYPES, REPORT; PDF_TYPES[REPORT] , т. е. 2 импорта для доступа к одному значению-это нехорошо.
  3. В виде списка, например if x not in PDF_TYPES: raise ValueError(....) .

Я посмотрел на классы данных, но они, похоже, предназначены для экземпляров вещей, это константы. Словарь был бы идеальным, если бы не неуклюжесть в scneario 2, в нем нет поиска атрибутов. Каков наиболее простой способ достижения вышеуказанных 3 требований?

Комментарии:

1. Использовать перечисление? docs.python.org/3/library/enum.html

2. Вероятно, вам просто нужно перечисление, но обратите внимание , что, вероятно, __iter__ должно быть что-то вроде yield self.summary; yield self.report того, что вы имели в виду iter([self.summary, self.report])

3. @juanpa.arrivillaga спасибо за это, но это метод класса, поэтому в нем нет «я».

4. @run_the_race что?

5. @juanpa.arrivillaga ваше решение self.summary включает в себя слово self , но PDF_TYPES не предназначено для создания экземпляра.

Ответ №1:

Похоже, перечисление-это то, что вы описываете

 from enum import Enum
class PDF_TYPES(Enum):
    summary = 'summary'
    report = 'report'
 

тогда, например

 >>> PDF_TYPES.summary
<PDF_TYPES.summary: 'summary'>

>>> for pdf_type in PDF_TYPES:
        print(pdf_type)
    
PDF_TYPES.summary
PDF_TYPES.report
 

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

 >>> any('report' == pdf_type.value for pdf_type in PDF_TYPES)
True
>>> any('foobar' == pdf_type.value for pdf_type in PDF_TYPES)
False
 

Комментарии:

1. Отлично, за исключением того, что нельзя проверить, скажем, 'report' in PDF_TYPES

2. @run_the_race Я обновил свой ответ, чтобы решить эту проблему. Хотя это не так просто, как использовать in , вы могли бы достичь этого с помощью any .