Próbując poprawić szybkość tego, są dwie uwagi: użycie Color.__members__.values()zamiast Koloru w map()rozmowie da od razu 30% doładowanie. Możesz wtedy uzyskać nieco większą prędkość, zastępując lambdę przez operator.attrgetter('value').
Giacomo Lacava
21
Na podstawie odpowiedzi @Jeff, refaktoryzowano, aby użyć a classmethod, aby można było ponownie użyć tego samego kodu dla dowolnego ze swoich wyliczeń:
class enum.Enumto klasa, która rozwiązuje wszystkie Twoje potrzeby związane z wyliczaniem, więc musisz po prostu dziedziczyć po niej i dodać własne pola. Od tego momentu wszystko, co musisz zrobić, to po prostu wywołać jego atrybuty: name& value:
from enum import Enum
classLetter(Enum):
A = 1
B = 2
C = 3
print({i.name: i.value for i in Letter})
# prints {'A': 1, 'B': 2, 'C': 3}
Więc Enumma __members__dyktando. Rozwiązanie zaproponowane przez @ozgur jest naprawdę najlepsze, ale możesz to zrobić, co robi to samo, przy większej ilości pracy
[color.value for color_name, color in Color.__members__.items()]
__members__Słownik mógłby się przydać, jeśli chcesz wstawić rzeczy dynamicznie w nim ... w jakiejś szalonej sytuacji.
[EDYCJA]
Najwyraźniej __members__nie jest słownikiem, ale mapą proxy. Co oznacza, że nie możesz łatwo dodawać do niego elementów.
Możesz jednak robić dziwne rzeczy, takie jak MyEnum.__dict__['_member_map_']['new_key'] = 'new_value', a potem możesz użyć nowego klucza, takiego jak MyEnum.new_key.... ale to tylko szczegół implementacji i nie powinno się nim bawić. Za czarną magię płacą ogromne koszty utrzymania.
Tylko pasek boczny: czy można dodawać elementy __members__? Byłby to interesujący sposób na zezwolenie na rozszerzenia, tworząc w ten sposób nowych Enumczłonków. ... przy okazji, głosowano za wprowadzeniem nowego ( dla mnie ) atrybutu do tabeli.
IAbstract
@IAbstract: Nie, to jest niedozwolone. Jeśli ktoś znajdzie sposób na dodawanie / odejmowanie członków po utworzeniu Enum, prawdopodobnie złamie to Enum.
Ethan Furman,
@IAbstract: Dodawanie nowych członków po fakcie zwykle nie jest dobrym pomysłem. Jeśli naprawdę chcesz, sprawdź tę odpowiedź .
Ethan Furman
2
Użyj, _member_names_aby szybko uzyskać łatwy wynik, jeśli są to tylko nazwy, tj
Color._member_names_
Masz również, _member_map_który zwraca uporządkowany słownik elementów. Funkcja ta zwraca collections.OrderedDict, więc trzeba Color._member_names_.items()i Color._member_names_.values()do zabawy. Na przykład
a = [(int(v), str(v)) for v in Color]
a potemprint(a)
.[(color.value, color.name) for color in Color]
Możesz wykonać następujące czynności:
[e.value for e in Color]
źródło
list(Color)
Aby użyć Enum z dowolnym typem wartości, spróbuj tego:
Zaktualizowany o kilka ulepszeń ... Dzięki @Jeff, twoja wskazówka!
from enum import Enum class Color(Enum): RED = 1 GREEN = 'GREEN' BLUE = ('blue', '#0000ff') @staticmethod def list(): return list(map(lambda c: c.value, Color)) print(Color.list())
W wyniku:
[1, 'GREEN', ('blue', '#0000ff')]
źródło
@classmethod
że wymagałoby to stworzenia instancjiColor
klasy. Dlategostaticmethod
wydaje się, że jest to właściwy wybór.@classmethod
i użyćreturn list(map(lambda c: c.value, cls))
zamiast tego.Color.__members__.values()
zamiast Koloru wmap()
rozmowie da od razu 30% doładowanie. Możesz wtedy uzyskać nieco większą prędkość, zastępując lambdę przezoperator.attrgetter('value')
.Na podstawie odpowiedzi @Jeff, refaktoryzowano, aby użyć a
classmethod
, aby można było ponownie użyć tego samego kodu dla dowolnego ze swoich wyliczeń:from enum import Enum class ExtendedEnum(Enum): @classmethod def list(cls): return list(map(lambda c: c.value, cls)) class OperationType(ExtendedEnum): CREATE = 'CREATE' STATUS = 'STATUS' EXPAND = 'EXPAND' DELETE = 'DELETE' print(OperationType.list())
Produkuje:
['CREATE', 'STATUS', 'EXPAND', 'DELETE']
źródło
class
enum.Enum
to klasa, która rozwiązuje wszystkie Twoje potrzeby związane z wyliczaniem, więc musisz po prostu dziedziczyć po niej i dodać własne pola. Od tego momentu wszystko, co musisz zrobić, to po prostu wywołać jego atrybuty:name
&value
:from enum import Enum class Letter(Enum): A = 1 B = 2 C = 3 print({i.name: i.value for i in Letter}) # prints {'A': 1, 'B': 2, 'C': 3}
źródło
Więc
Enum
ma__members__
dyktando. Rozwiązanie zaproponowane przez @ozgur jest naprawdę najlepsze, ale możesz to zrobić, co robi to samo, przy większej ilości pracy[color.value for color_name, color in Color.__members__.items()]
__members__
Słownik mógłby się przydać, jeśli chcesz wstawić rzeczy dynamicznie w nim ... w jakiejś szalonej sytuacji.[EDYCJA] Najwyraźniej
__members__
nie jest słownikiem, ale mapą proxy. Co oznacza, że nie możesz łatwo dodawać do niego elementów.Możesz jednak robić dziwne rzeczy, takie jak
MyEnum.__dict__['_member_map_']['new_key'] = 'new_value'
, a potem możesz użyć nowego klucza, takiego jakMyEnum.new_key
.... ale to tylko szczegół implementacji i nie powinno się nim bawić. Za czarną magię płacą ogromne koszty utrzymania.źródło
__members__
? Byłby to interesujący sposób na zezwolenie na rozszerzenia, tworząc w ten sposób nowychEnum
członków. ... przy okazji, głosowano za wprowadzeniem nowego ( dla mnie ) atrybutu do tabeli.Użyj,
_member_names_
aby szybko uzyskać łatwy wynik, jeśli są to tylko nazwy, tjMasz również,
_member_map_
który zwraca uporządkowany słownik elementów. Funkcja ta zwracacollections.OrderedDict
, więc trzebaColor._member_names_.items()
iColor._member_names_.values()
do zabawy. Na przykładreturn list(map(lambda x: x.value, Color._member_map_.values()))
zwróci wszystkie prawidłowe wartości Color
źródło
Korzystanie
classmethod
z__members__
:class RoleNames(str, Enum): AGENT = "agent" USER = "user" PRIMARY_USER = "primary_user" SUPER_USER = "super_user" @classmethod def list_roles(cls): role_names = [member.value for role, member in cls.__members__.items()] return role_names
lub jeśli masz wiele klas Enum i chcesz wyodrębnić metodę klasy:
class BaseEnum(Enum): @classmethod def list_roles(cls): role_names = [member.value for role, member in cls.__members__.items()] return role_names class RoleNames(str, BaseEnum): AGENT = "agent" USER = "user" PRIMARY_USER = "primary_user" SUPER_USER = "super_user" class PermissionNames(str, BaseEnum): READ = "updated_at" WRITE = "sort_by" READ_WRITE = "sort_order"
źródło