Выберите из python enum по значению члена - PullRequest
1 голос
/ 29 января 2020

Как я могу получить все экземпляры класса enum, которые соответствуют критерию для данного, но неизвестного поля?

У меня есть следующие три класса, полученные из Enum, два простых (VariableType и VariableCategory) и один, в котором экземпляры фактически хранят содержимое в полях (Variable).

class VariableCategory(Enum):
    SHORT = auto()
    MEDIUM = auto()
    LONG = auto()

class VariableType(Enum):
    ONE = auto()
    TWO = auto()

class Variable(Enum):
    A = ('Variable A',
           VariableCategory.SHORT,
           VariableType.ONE,
           1)
    B = ('Variable B',
           VariableCategory.MEDIUM,
           VariableType.TWO,
           2)
    C = ('Variable V',
           VariableCategory.SHORT,
           VariableType.TWO,
           3)

    def __init__(self, name: str, variable_category: VariableCategory, variable_type: VariableType,
                 number:int) -> None:
        self.name = name
        self.variable_category = variable_category
        self.variable_type = variable_type
        self.number = number

Теперь я хотел бы создать функцию класса, которая может принимать произвольный параметр введите VariableType или VariableCategory и верните все соответствующие экземпляры Variable:

@classmethod
def by_x(cls, x: Union[VariableType, VariableCategory]):
    # something like return [cls[member] for member in cls.__members__ if x in cls[member]]

Например, если дано VariableType соответствующих экземпляров Variable, например:

>>> Variable.by_x(VariableType.ONE)
    [Variable.A]
>>> Variable.by_x(VariableType.TWO)
    [Variable.B, Variable.C]
>>> Variable.by_x(VariableCategory.SHORT)
    [Variable.A, Variable.C]
>>> Variable.by_x(VariableCategory.MEDIUM)
    [Variable.B]
>>> Variable.by_x(VariableCategory.LONG)
    []

Я также знаю, что могу использовать более специфичные c функции для одного из полей перечисления Variable:

@classmethod
def by_variable_type(cls, variable_type: VariableType) -> List['Variable']:
    return [cls[member] for member in cls.__members__ if cls[member].variable_type == variable_type]

Однако я не знаю, как сделать только одна, функция generi c вместо множества указанных c (то есть без проверки типа параметра и вызова соответствующего решения c соответственно).

Ответы [ 2 ]

2 голосов
/ 29 января 2020
    @classmethod
    def by_x(cls, criterion):
        return [
                m
                for m in cls
                if m.variable_category == criterion
                    or m.variable_type == criterion
                    ]

Кроме того, вы не можете присвоить self.name - это поднимает AttributeError.

1 голос
/ 31 января 2020

Это решение делает то, что вы хотите.

Метод класса get_by_values может получить список или список списков с любой комбинацией значений, которые вы хотите удовлетворить. Он гарантирует возвращение только тех участников, которые полностью удовлетворили одну из пройденных вами комбинаций. Он возвращает set из Enum членов, поэтому нет повторений. Если вы используете список в ответе, вы получите упорядоченные результаты, соответствующие каждому передаваемому аргументу.

Variable члены уже имеют Variable.name, с которым вы их объявляете. Если вы хотите что-то более выразительное, я бы go с __str__ или __init__, возможно, в сочетании с VariableCategory.name и VariableType.name.

from enum import Enum, auto


class VariableCategory(Enum):
    SHORT = auto()
    MEDIUM = auto()
    LONG = auto()


class VariableType(Enum):
    ONE = auto()
    TWO = auto()


class Variable(Enum):
    A = VariableCategory.SHORT, VariableType.ONE
    B = VariableCategory.MEDIUM, VariableType.TWO
    C = VariableCategory.SHORT, VariableType.TWO

    def __init__(self, variable_category: VariableCategory, variable_type: VariableType):
        self.variable_category = variable_category
        self.variable_type = variable_type

    def in_value(self, argument):
        if set(argument).issubset(set(self.value)):
            return self

    @classmethod
    def get_by_values(cls, *args):
        return {member for member in cls
                if member in {member.in_value(arg) for arg in args}}


first = [VariableCategory.SHORT, VariableType.ONE]
second = [VariableCategory.SHORT]

print(*Variable.get_by_values(first, second))
# Variable.A Variable.C

print(*Variable.get_by_values([VariableCategory.MEDIUM]))
# Variable.B

print(*Variable.get_by_values([VariableType.TWO]))
# Variable.B Variable.C

РЕДАКТИРОВАТЬ: Заменено на с установленным пониманием. Расширенный раздел для ниже:

def in_value(self, argument):

    for element in argument:
        if element not in self.value:
            return False

    return True

@classmethod
def get_by_values(cls, *args):
    result = list()

    for one_member in Variable:
        for argument in args:
            if one_member.in_value(argument):
                if one_member not in result:
                    result.append(one_member)

    return result
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...