Hur Enums i Python förbättrar kodläsbarheten

By rik

Enums, eller uppräkningstyper, är en populär funktion i många programmeringsspråk, som C, C++ och Java. De bidrar till att skapa kod som är både typsäker och lättare att läsa.

I Python fanns det inte alltid stöd för enums, men sedan version 3.4 har Python infört detta. Denna artikel ger en översikt över hur man skapar och använder enums, samt hur de kan förbättra kodens tydlighet.

Vad är Enums och vad gör de?

En uppräkning är en datatyp som är definierad av en specifik uppsättning av möjliga värden. Denna uppsättning värden kallas för dess medlemmar. Enums ger möjlighet att begränsa de värden en variabel kan ha, vilket leder till mer typsäker kod och ökad läsbarhet.

Några villkor att känna till

Innan vi går djupare in på enums, är det bra att definiera några termer som vi kommer att använda ofta: medlemmar och värden.

  • Medlemmar: Dessa är de namngivna konstanterna som utgör de möjliga värdena för en enum. Till exempel, en enum som representerar veckodagar kan ha medlemmarna: måndag, tisdag, onsdag, och så vidare.
  • Värden: Varje enummedlem har ett internt värde som används för att representera den unikt. Detta gör det möjligt att jämföra medlemmar. Exempelvis kan måndag ha värdet 0, tisdag värdet 1, och så vidare.

Nu ska vi se hur enums bidrar till att förbättra koden.

Hur Enums förbättrar din kod

Enums gör koden mer läsbar, minskar risken för fel och förbättrar på så sätt den totala kodkvaliteten. Här är några fördelar med att använda enums:

  • Enums gör det tydligt vilka värden en variabel eller ett funktionsargument förväntas ta emot. Detta gör det enklare för andra att förstå vad koden gör.
  • Enums gör koden mer självförklarande, vilket minskar behovet av kommentarer och dokumentation. Genom att använda en enum specificeras de förväntade värdena tydligt.
  • Integrerade utvecklingsmiljöer (IDE) kan upptäcka felaktiga värden och ge förslag på autokomplettering, vilket underlättar programmeringen.
  • Resultatet är en mer typsäker kod med färre potentiella fel vid körning.

Låt oss nu se hur man skapar enums i Python.

Hur man skapar enums i Python

Python har inte ett inbyggt stöd för enums, men det finns en enum-modul i standardbiblioteket. Vi kommer att använda denna modul i den här genomgången. Det finns två sätt att skapa enums i Python: via klasser eller via en funktions-API. Vi ska gå igenom båda metoderna.

Förutsättningar

För att följa denna genomgång behöver du Python 3.4 eller senare. Denna version av Python innehåller enum-modulen. Om du inte har den installerad, kan du följa denna guide för att installera Python.

Du behöver också ha grundläggande kunskaper i Python, inklusive grundläggande Python-syntax och objektorienterade programmeringskoncept som klasser och arv.

#1. Klassmetoden

Det första sättet att skapa en enum är att använda klasser. Du importerar klassen Enum från modulen enum. Sedan skapar du din egen enum genom att definiera en klass som ärver från Enum.

from enum import Enum

class Direction(Enum):
    NORTH = 0
    EAST = 1
    SOUTH = 2
    WEST = 3

Du kan även tilldela valfria värden till enums medlemmar. Här är ett exempel där vi tilldelar varje riktning dess motsvarande gradtal istället för 0, 1, 2 och 3:

from enum import Enum

class Direction(Enum):
    NORTH = 0
    EAST = 90
    SOUTH = 180
    WEST = 270

Alternativt kan du använda range()-funktionen för att skapa värden på ett mer kortfattat sätt:

from enum import Enum

class Direction(Enum):
    NORTH, EAST, SOUTH, WEST = range(0, 360, 90)

Här genererar vi värden med range()-funktionen. Vi anger 0 som startvärde, 360 som slutvärde, och 90 som steg. Värdena distribueras sedan till de olika medlemmarna. Om du vill veta mer om strukturerad data, kan du läsa om tupler i Python.

Enum-klasser är abstrakta klasser, vilket innebär att de inte är menade att instansieras. Istället använder du deras egenskaper direkt för att komma åt enummedlemmarna.

#2. Funktionsmetoden

Funktionsmetoden är ett alternativ till att ärva en klass:

from enum import Enum

Direction = Enum("Direction", ["NORTH", "EAST", "SOUTH", "WEST"])

I koden ovan skapar vi en enum vid namn ”Direction” genom att ange ett namn och en lista med medlemmar som ett andra argument. Som standard får varje medlem värden från 1 och uppåt. Så ”NORTH” blir 1, ”EAST” blir 2, och så vidare. Detta beror på att 0 är falskt i boolesk logik, så för att alla värden ska vara ”sanna” börjar de numreras från 1.

Du kan också ange specifika värden för medlemmarna genom att skicka in en lista av tupler. Varje tupel innehåller namnet på medlemmen och dess motsvarande värde.

from enum import Enum

Direction = Enum(
    name = "Direction",
    values = [
        ("NORTH", "n"),
        ("EAST", "e"),
        ("SOUTH", "s"),
        ("WEST", "w"),
    ]
)

I exemplet ovan använde vi strängar istället för heltal för att tilldela värden. Detta visar att strängar är lika giltiga som heltal för att representera värden i en enum.

Hur man använder Enums

I föregående avsnitt såg vi hur man skapar enums och ger dem värden. Nu ska vi titta på hur man använder enums för att komma åt, tilldela och jämföra medlemmar.

Hur man får åtkomst till medlemmar

Det finns flera sätt att komma åt medlemmar i en enum, inklusive punktnotation, hakparenteser, och vanliga parenteser. Här är ett exempel som demonstrerar dessa:

from enum import Enum

# Skapa en enum
class Day(Enum):
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY = range(1, 8)

# Åtkomst till enums medlemmar
# 1. Med punktnotation
print(Day.SUNDAY)

# 2. Med hakparenteser
print(Day["MONDAY"])

# 3. Med parenteser
print(Day(3))

När du har kommit åt en enummedlem kan du spara den i en variabel. Tänk på att det du får är en referens till medlemsobjektet, inte dess värde eller namn. Detta är viktigt att komma ihåg för kommande exempel.

Få åtkomst till namnet och värdet

Som nämnts tidigare, refererar en enummedlem till själva objektet. Om du vill komma åt namnet eller värdet för en medlem, kan du använda egenskaperna .name och .value:

print(Day.SUNDAY.name, Day.SUNDAY.value)

Kontrollerar jämställdhet

Kom ihåg att tilldela en enummedlem till en variabel skapar en referens till enummedlemsobjektet. För att kontrollera om en variabel pekar på samma enummedlem använder vi operatorn `is` för att jämföra objektreferenser.

Här är ett exempel:

today = Day.WEDNESDAY

if today is Day.MONDAY:
    print("Det är måndag, :(")

if today is Day.WEDNESDAY:
    print("Glad onsdag")

Alternativt kan du använda operatorn `==`. För subklasser av Enum är `==`-operatorn en ”wrapper” för `is`-operatorn. Detta åstadkoms med hjälp av operatörsöverbelastning. Här är ett exempel som använder `==` istället för `is`:

today = Day.WEDNESDAY

if today == Day.MONDAY:
    print("Det är måndag, :(")

if today == Day.WEDNESDAY:
    print("Glad onsdag")

För att repetera, jämförelser med enummedlemmar görs genom att jämföra objektreferenser, inte värden.

Slutord

Den här artikeln har gått igenom vad enums är, varför de är användbara, och de olika sätten att skapa enums, både genom att ärva Enum-klassen och genom att använda funktions-API:et.

Vi har också tittat på hur man använder enums, får tillgång till deras medlemmar, och gör jämförelser. Du kanske också är intresserad av att läsa om Enums i TypeScript.