1
votes

Liste d'itération ou d'index basée sur Enum

J'ai une petite liste d'énumérations de 4 éléments ( class Type (Enum): One, Two, Three, Four ), et je me demande s'il existe un moyen d'associer l'énumération à une liste globale ( List = [Type (0), Type (1), Type (2), Type (3) ].

Je sais que je peux accéder à cette liste en utilisant la syntaxe List [Type.Two.value] . Mais j'espère qu'il existe un moyen simple de perdre la .value . Ce n'est pas un problème de frappe - cela ne me dérange pas de taper de longs noms de variables descriptives. Mais la liste et l'énumération sont directement liées / associées, il serait donc préférable que la liste respecte l'énumération en tant qu'itérateur. Y a-t-il un moyen simple d'y parvenir?

Je travaille dans l'environnement de Blender, construisant un add-on, si cela fait une différence. Je suis également très novice en python - il a environ une semaine, alors n'omettez pas les points évidents si vous en avez.

Je connais très bien le C / C ++, au cas où il y aurait des similitudes. J'étais un grand fan de créer des listes de bibliothèques de données et d'associer des types d'itérateurs d'une manière qui empêchait l'accès à la liste en utilisant autre chose que le nom de type d'index qui lui était associé (vous ne pouviez donc pas faire une erreur comme Cars [my_boat_index] )

J'apprécie tous les conseils!


0 commentaires

3 Réponses :


0
votes

Il semble que vous cherchiez à restreindre l'accès à une liste en limitant le type d'index à un type spécifique (par exemple, un Enum).

Bien que je ne pense pas que ce soit une bonne idée, vous pouvez certainement le faire it:

for my_value in MyEnum:
    print(ml[my_value])

Pourquoi voudriez-vous restreindre l'accès à une liste à un type différent du type par défaut pour l'index de liste (c'est-à-dire int ) ?

Si vous cherchez à avoir des attributs spécifiques, pourquoi ne pas définir une classe, ou si vous voulez indexer des valeurs spécifiques, pourquoi ne pas utiliser un dict?

Peut-être devriez-vous fournissez des informations sur ce que vous espérez réellement faire - Python n'est pas C / C ++ et il a probablement une manière parfaitement valide de faire ce que vous voulez faire, sans avoir à émuler ce que fait C / C ++ à la place.

Si vous ne cherchez pas à restreindre, mais simplement à itérer (ce qui semble être distinct de ce que la question énonce):

from enum import Enum


class MyEnum(Enum):
    ZERO = 0
    ONE = 1
    TWO = 2


class MyList(list):
    def __getitem__(self, item):
        assert isinstance(item, MyEnum)
        return super().__getitem__(item.value)


ml = MyList([1, 2, 3])
print(ml[MyEnum.ONE])
print(ml[1])  # error here

Vous pouvez alors omettre le Instruction assert , si vous n'êtes pas intéressé à limiter l'accès aux index avec t type de chapeau uniquement.


1 commentaires

Je n'essaye pas de restreindre l'accès à la liste. Itérez simplement avec les valeurs de l'énumérateur. L'environnement de Blender semble être très restrictif lorsqu'il s'agit de définir des types personnalisés pour les propriétés, donc je ne suis pas sûr de ce que je peux encore faire. Quant au C / C ++, je viens de mentionner que je le connais au cas où il y aurait des similitudes qui rendraient la situation python plus facile à expliquer. Aucune autre raison. Merci de m'avoir montré ce type de configuration. Je ne suis pas sûr que Blender me permettra de créer des groupes de propriétés, avec un type de liste personnalisé, mais je vais quand même essayer.



0
votes

À partir de la documentation https://docs.python.org/3/library/ enum.html Les énumérations prennent en charge l'itération, dans l'ordre des définitions afin que vous puissiez les parcourir pour créer des listes, par exemple:

from enum import Enum

class Numbers(Enum):
    ONE = 1
    TWO = 2
    THREE = 3

assert [Number.value for Number in Numbers]  == [1,2,3]



0 commentaires

0
votes

Transformer un Enum en liste est aussi simple que:

class Type(Enum):
    ONE = 1
    TWO = 2
    THREE = 3
    FOUR = 4

    def __index__(self):
        return self.value - 1

    def __int__(self):
        return self.value - 1

Accéder à une liste en utilisant des membres Type comme index est un peu plus compliqué:

  • par défaut, les valeurs des membres commencent à 1
  • mais les index de conteneur commencent à 0
  • et les membres ne disposent pas des méthodes __index__ et __int__

La solution facile / simple est double:

  • utilisez IntEnum au lieu de Enum
  • démarrer le comptage à 0

So:

class Type(IntEnum):
    ZERO = 0
    ONE = 1
    TWO = 2
    THREE = 3

Les membres IntEnum peuvent être utilisés partout où se trouve un int , donc ils fonctionnent bien comme valeurs d'index.

La solution la plus compliquée consiste à utiliser un Enum normal, à ajouter les méthodes dont vous avez besoin et à soustraire 1 lors du renvoi de la valeur:

list(Type)
# [<Type.ONE: 1>, <Type.TWO: 2>, <Type.THREE: 3>, <Type.FOUR: 4>]

Même si vous ajoutez les méthodes __index__ et __int__ , vous devriez quand même commencer à compter à zéro au lieu de faire la soustraction une astuce, car cela posera plus de problèmes plus tard lorsque vous vous habituerez au fonctionnement de Python.


1 commentaires

On dirait qu'IntEnum correspond bien à ma situation. Merci d'avoir expliqué si en détail.