Thursday, February 2, 2023
Learning Code
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
Learning Code
No Result
View All Result
Home Python

Build Enumerations of Constants With Python’s Enum – Real Python

learningcode_x1mckf by learningcode_x1mckf
October 3, 2022
in Python
0
Build Enumerations of Constants With Python’s Enum – Real Python
74
SHARES
1.2k
VIEWS
Share on FacebookShare on Twitter


Python’s enum module offers the Enum class, which lets you create enumeration varieties. To create your individual enumerations, you possibly can both subclass Enum or use its purposeful API. Each choices will allow you to outline a set of associated constants as enum members.

Within the following sections, you’ll learn to create enumerations in your code utilizing the Enum class. You’ll additionally learn to set robotically generated values in your enums and tips on how to create enumerations containing alias and distinctive values. To kick issues off, you’ll begin by studying tips on how to create an enumeration by subclassing Enum.

Creating Enumerations by Subclassing Enum

The enum module defines a general-purpose enumeration kind with iteration and comparison capabilities. You should use this kind to create units of named constants that you need to use to exchange literals of frequent information varieties, resembling numbers and strings.

A basic instance of when you need to use an enumeration is when you want to create a set of enumerated constants representing the times of the week. Every day can have a symbolic title and a numeric worth between 1 and 7, inclusive.

Right here’s how one can create this enumeration through the use of Enum as your superclass or guardian class:

>>>

>>> from enum import Enum

>>> class Day(Enum):
...     MONDAY = 1
...     TUESDAY = 2
...     WEDNESDAY = 3
...     THURSDAY = 4
...     FRIDAY = 5
...     SATURDAY = 6
...     SUNDAY = 7
...

>>> checklist(Day)
[
    <Day.MONDAY: 1>,
    <Day.TUESDAY: 2>,
    <Day.WEDNESDAY: 3>,
    <Day.THURSDAY: 4>,
    <Day.FRIDAY: 5>,
    <Day.SATURDAY: 6>,
    <Day.SUNDAY: 7>
]

Your Day class is a subclass of Enum. So, you possibly can name Day an enumeration, or simply an enum. Day.MONDAY, Day.TUESDAY, and the like are enumeration members, also called enum members, or simply members. Every member will need to have a worth, which must be fixed.

As a result of enumeration members should be constants, Python doesn’t can help you assign new values to enum members at runtime:

>>>

>>> Day.MONDAY = 0
Traceback (most up-to-date name final):
    ...
AttributeError: Can't reassign members.

>>> Day
<enum 'Day'>

>>> # Rebind Day
>>> Day = "Monday"
>>> Day
'Monday'

In case you attempt to change the worth of an enum member, then you definitely get an AttributeError. In contrast to member names, the title containing the enumeration itself isn’t a continuing however a variable. So, it’s doable to rebind this title at any second throughout your program’s execution, however you need to keep away from doing that.

Within the instance above, you’ve reassigned Day, which now holds a string quite than the unique enumeration. By doing this, you’ve misplaced the reference to the enum itself.

Typically, the values mapped to members are consecutive integer numbers. Nevertheless, they are often of any kind, together with user-defined varieties. On this instance, the worth of Day.MONDAY is 1, the worth of Day.TUESDAY is 2, and so forth.

Word: You might have seen that the members of Day are capitalized. Right here’s why:

As a result of Enums are used to characterize constants we advocate utilizing UPPER_CASE names for enum members… (Source)

You may consider enumerations as collections of constants. Like lists, tuples, or dictionaries, Python enumerations are additionally iterable. That’s why you need to use list() to show an enumeration right into a checklist of enumeration members.

The members of a Python enumeration are cases of the container enumeration itself:

>>>

>>> from enum import Enum

>>> class Day(Enum):
...     MONDAY = 1
...     TUESDAY = 2
...     WEDNESDAY = 3
...     THURSDAY = 4
...     FRIDAY = 5
...     SATURDAY = 6
...     SUNDAY = 7
...

>>> kind(Day.MONDAY)
<enum 'Day'>

>>> kind(Day.TUESDAY)
<enum 'Day'>

You shouldn’t confuse a customized enum class like Day with its members: Day.MONDAY, Day.TUESDAY, and so forth. On this instance, the Day enum kind is a hub for enumeration members, which occur to be of kind Day.

It’s also possible to use the idiom based mostly on range() to construct enumerations:

>>>

>>> from enum import Enum

>>> class Season(Enum):
...     WINTER, SPRING, SUMMER, FALL = vary(1, 5)
...

>>> checklist(Season)
[
    <Season.WINTER: 1>,
    <Season.SPRING: 2>,
    <Season.SUMMER: 3>,
    <Season.FALL: 4>
]

On this instance, you employ vary() with the begin and cease offsets. The begin offset permits you to present the quantity that begins the vary, whereas the cease offset defines the quantity at which the vary will cease producing numbers.

Regardless that you employ the class syntax to create enumerations, they’re particular lessons that differ from regular Python lessons. In contrast to common lessons, enums:

You need to remember all these refined variations if you begin creating and dealing with your individual enumerations in Python.

Typically, the members of an enumeration take consecutive integer values. Nevertheless, in Python, the values of members will be of any kind, together with user-defined varieties. For instance, right here’s an enumeration of faculty grades that makes use of non-consecutive numeric values in descending order:

>>>

>>> from enum import Enum

>>> class Grade(Enum):
...     A = 90
...     B = 80
...     C = 70
...     D = 60
...     F = 0
...

>>> checklist(Grade)
[
    <Grade.A: 90>,
    <Grade.B: 80>,
    <Grade.C: 70>,
    <Grade.D: 60>,
    <Grade.F: 0>
]

This instance exhibits that Python enums are fairly versatile and can help you use any significant worth for his or her members. You may set the member values in keeping with the intent of your code.

It’s also possible to use string values in your enumeration members. Right here’s an instance of a Dimension enumeration that you need to use in a web-based retailer:

>>>

>>> from enum import Enum

>>> class Dimension(Enum):
...     S = "small"
...     M = "medium"
...     L = "giant"
...     XL = "further giant"
...

>>> checklist(Dimension)
[
    <Size.S: 'small'>,
    <Size.M: 'medium'>,
    <Size.L: 'large'>,
    <Size.XL: 'extra large'>
]

On this instance, the worth related to every dimension holds an outline that may assist you to and different builders perceive the that means of your code.

It’s also possible to create enumerations of Boolean values. On this case, the members of your enumeration can have solely two values:

>>>

>>> from enum import Enum

>>> class SwitchPosition(Enum):
...     ON = True
...     OFF = False
...

>>> checklist(SwitchPosition)
[<SwitchPosition.ON: True>, <SwitchPosition.OFF: False>]

>>> class UserResponse(Enum):
...     YES = True
...     NO = False
...

>>> checklist(UserResponse)
[<UserResponse.YES: True>, <UserResponse.NO: False>]

These two examples present how you need to use enumerations so as to add further context to your code. Within the first instance, anybody studying your code will know that the code emulates a change object with two doable states. This extra info extremely improves your code’s readability.

It’s also possible to outline an enumeration with heterogeneous values:

>>>

>>> from enum import Enum

>>> class UserResponse(Enum):
...     YES = 1
...     NO = "No"
...

>>> UserResponse.NO
<UserResponse.NO: 'No'>

>>> UserResponse.YES
<UserResponse.YES: 1>

Nevertheless, this apply makes your code inconsistent from a type safety perspective. Due to this fact, it’s not really helpful apply. Ideally, it could assist in the event you had values of the identical information kind, which is per the thought of grouping related, associated constants in enumerations.

Lastly, you too can create empty enumerations:

>>>

>>> from enum import Enum

>>> class Empty(Enum):
...     go
...

>>> checklist(Empty)
[]

>>> class Empty(Enum):
...     ...
...

>>> checklist(Empty)
[]

>>> class Empty(Enum):
...     """Empty enumeration for such and such functions."""
...

>>> checklist(Empty)
[]

On this instance, Empty represents an empty enumeration as a result of it doesn’t outline any member constants. Word that you need to use the pass assertion, the Ellipsis literal (...), or a class-level docstring to create empty enumerations. This final method may help you enhance the readability of your code by offering further context within the docstring.

Now, why would you want to outline an empty enumeration anyway? Empty enumerations can come in useful when you want to construct a hierarchy of enum lessons to reuse performance via inheritance.

Think about the next instance:

>>>

>>> from enum import Enum
>>> import string

>>> class BaseTextEnum(Enum):
...     def as_list(self):
...         strive:
...             return checklist(self.worth)
...         besides TypeError:
...             return [str(self.value)]
...

>>> class Alphabet(BaseTextEnum):
...     LOWERCASE = string.ascii_lowercase
...     UPPERCASE = string.ascii_uppercase
...

>>> Alphabet.LOWERCASE.as_list()
['a', 'b', 'c', 'd', ..., 'x', 'y', 'z']

On this instance, you create BaseTextEnum as an enumeration with no members. You may solely subclass a customized enumeration if it doesn’t have members, so BaseTextEnum qualifies. The Alphabet class inherits out of your empty enumeration, which implies you can entry the .as_list() technique. This technique converts the worth of a given member into an inventory.

Creating Enumerations With the Practical API

The Enum class offers a functional API that you need to use to create enumerations with out utilizing the same old class syntax. You’ll simply have to name Enum with acceptable arguments such as you’d do with a function or another callable.

You might also like

Build a JavaScript Front End for a Flask API – Real Python

Using the Terminal on Linux – Real Python

How to Iterate Over Rows in pandas, and Why You Shouldn’t – Real Python

This purposeful API resembles the best way wherein the namedtuple() manufacturing facility perform works. Within the case of Enum, the purposeful signature has the next kind:

Enum(
    worth,
    names,
    *,
    module=None,
    qualname=None,
    kind=None,
    begin=1
)

From this signature, you possibly can conclude that Enum wants two positional arguments, worth and names. It may well additionally take as much as 4 optional and keyword-only arguments. These arguments are module, qualname, kind, and begin.

Right here’s a desk that summarizes the content material and that means of every argument within the signature of Enum:

Argument Description Required
worth Holds a string with the title of the brand new enumeration class Sure
names Supplies names for the enumeration members Sure
module Takes the title of the module that defines the enumeration class No
qualname Holds the placement of the module that defines the enumeration class No
kind Holds a category for use as the primary mixin class No
begin Takes the beginning worth from the enumeration values will start No

To supply the names argument, you need to use the next objects:

  • A string containing member names separated both with areas or commas
  • An iterable of member names
  • An iterable of name-value pairs

The module and qualname arguments play an essential position when you want to pickle and unpickle your enumerations. If module isn’t set, then Python will try to search out the module. If it fails, then the category is not going to be picklable. Equally, if qualname isn’t set, then Python will set it to the global scope, which can trigger your enumerations to fail unpickling in some conditions.

The kind argument is required if you wish to present a mixin class in your enumeration. Utilizing a mixin class can present your customized enum with new performance, resembling prolonged comparability capabilities, as you’ll be taught within the part about mixing enumerations with other data types.

Lastly, the begin argument offers a approach to customise the preliminary worth of your enumerations. This argument defaults to 1 quite than to 0. The rationale for this default worth is that 0 is fake in a Boolean sense, however enum members consider to True. Due to this fact, ranging from 0 would appear shocking and complicated.

More often than not, you’ll simply use the primary two arguments to Enum when creating your enumerations. Right here’s an instance of making an enumeration of frequent HTTP methods:

>>>

>>> from enum import Enum

>>> HTTPMethod = Enum(
...     "HTTPMethod", ["GET", "POST", "PUSH", "PATCH", "DELETE"]
... )

>>> checklist(HTTPMethod)
[
    <HTTPMethod.GET: 1>,
    <HTTPMethod.POST: 2>,
    <HTTPMethod.PUSH: 3>,
    <HTTPMethod.PATCH: 4>,
    <HTTPMethod.DELETE: 5>
]

This name to Enum returns a brand new enumeration known as HTTPMethod. To supply the member names, you employ an inventory of strings. Every string represents an HTTP technique. Word that the member values are robotically set to consecutive integer numbers ranging from 1. You may change this preliminary worth utilizing the begin argument.

Word that defining the above enumerations with the category syntax will produce the identical outcome:

>>>

>>> from enum import Enum

>>> class HTTPMethod(Enum):
...     GET = 1
...     POST = 2
...     PUSH = 3
...     PATCH = 4
...     DELETE = 5
...

>>> checklist(HTTPMethod)
[
    <HTTPMethod.GET: 1>,
    <HTTPMethod.POST: 2>,
    <HTTPMethod.PUSH: 3>,
    <HTTPMethod.PATCH: 4>,
    <HTTPMethod.DELETE: 5>
]

Right here, you employ the category syntax to outline the HTTPMethod enum. This instance is totally equal to the earlier one, as you possibly can conclude from the output of checklist().

Utilizing both the category syntax or the purposeful API to create your enumeration is your determination and can largely rely in your style and concrete circumstances. Nevertheless, if you wish to create enumerations dynamically, then the purposeful API will be your solely choice.

Think about the next instance, the place you create an enum with user-provided members:

>>>

>>> from enum import Enum

>>> names = []
>>> whereas True:
...     title = enter("Member title: ")
...     if title in "q", "Q":
...         break
...     names.append(title.higher())
...
Member title: YES
Member title: NO
Member title: q

>>> DynamicEnum = Enum("DynamicEnum", names)
>>> checklist(DynamicEnum)
[<DynamicEnum.YES: 1>, <DynamicEnum.NO: 2>]

This instance is a bit bit excessive as a result of creating any object out of your person’s enter is sort of a dangerous apply, contemplating you can’t predict what the person will enter. Nevertheless, the instance is meant to indicate that the purposeful API is the best way to go when you want to create enumerations dynamically.

Lastly, if you want to set customized values in your enum members, then you need to use an iterable of name-value pairs as your names argument. Within the instance beneath, you employ an inventory of name-value tuples to initialize all of the enumeration members:

>>>

>>> from enum import Enum

>>> HTTPStatusCode = Enum(
...     worth="HTTPStatusCode",
...     names=[
...         ("OK", 200),
...         ("CREATED", 201),
...         ("BAD_REQUEST", 400),
...         ("NOT_FOUND", 404),
...         ("SERVER_ERROR", 500),
...     ],
... )

>>> checklist(HTTPStatusCode)
[
    <HTTPStatusCode.OK: 200>,
    <HTTPStatusCode.CREATED: 201>,
    <HTTPStatusCode.BAD_REQUEST: 400>,
    <HTTPStatusCode.NOT_FOUND: 404>,
    <HTTPStatusCode.SERVER_ERROR: 500>
]

Offering an inventory of name-value tuples such as you did above makes it doable to create the HTTPStatusCode enumeration with customized values for the members. On this instance, in the event you didn’t wish to use an inventory of name-value tuples, then you can additionally use a dictionary that maps names to values.

Constructing Enumerations From Computerized Values

Python’s enum module offers a handy perform known as auto() that permits you to set computerized values in your enum members. This perform’s default habits is to assign consecutive integer values to members.

Right here’s how auto() works:

>>>

>>> from enum import auto, Enum

>>> class Day(Enum):
...     MONDAY = auto()
...     TUESDAY = auto()
...     WEDNESDAY = 3
...     THURSDAY = auto()
...     FRIDAY = auto()
...     SATURDAY = auto()
...     SUNDAY = 7
...

>>> checklist(Day)
[
    <Day.MONDAY: 1>,
    <Day.TUESDAY: 2>,
    <Day.WEDNESDAY: 3>,
    <Day.THURSDAY: 4>,
    <Day.FRIDAY: 5>,
    <Day.SATURDAY: 6>,
    <Day.SUNDAY: 7>
]

You have to name auto() as soon as for every computerized worth that you simply want. It’s also possible to mix auto() with concrete values, identical to you probably did with Day.WEDNESDAY and Day.SUNDAY on this instance.

By default, auto() assigns consecutive integer numbers to every goal member ranging from 1. You may tweak this default habits by overriding the ._generate_next_value_() technique, which auto() makes use of below the hood to generate the automated values.

Right here’s an instance of how to do that:

>>>

>>> from enum import Enum, auto

>>> class CardinalDirection(Enum):
...     def _generate_next_value_(title, begin, rely, last_values):
...         return title[0]
...     NORTH = auto()
...     SOUTH = auto()
...     EAST = auto()
...     WEST = auto()
...

>>> checklist(CardinalDirection)
[
    <CardinalDirection.NORTH: 'N'>,
    <CardinalDirection.SOUTH: 'S'>,
    <CardinalDirection.EAST: 'E'>,
    <CardinalDirection.WEST: 'W'>
]

On this instance, you create an enumeration of Earth’s cardinal directions wherein values are robotically set to strings containing the primary character of every member’s title. Word that you could present your overridden model of ._generate_next_value_() earlier than defining any members. That’s as a result of the members shall be constructed by calling the strategy.

Creating Enumerations With Aliases and Distinctive Values

You may create enumerations wherein two or extra members have the identical fixed worth. The redundant members are referred to as aliases and will be helpful in some conditions. For instance, say that you’ve an enum containing a set of working methods (OS), like within the following code:

>>>

>>> from enum import Enum

>>> class OperatingSystem(Enum):
...     UBUNTU = "linux"
...     MACOS = "darwin"
...     WINDOWS = "win"
...     DEBIAN = "linux"
...

>>> # Aliases aren't listed
>>> checklist(OperatingSystem)
[
    <OperatingSystem.UBUNTU: 'linux'>,
    <OperatingSystem.MACOS: 'darwin'>,
    <OperatingSystem.WINDOWS: 'win'>
]

>>> # To entry aliases, use __members__
>>> checklist(OperatingSystem.__members__.gadgets())
[
    ('UBUNTU', <OperatingSystem.UBUNTU: 'linux'>),
    ('MACOS', <OperatingSystem.MACOS: 'darwin'>),
    ('WINDOWS', <OperatingSystem.WINDOWS: 'win'>),
    ('DEBIAN', <OperatingSystem.UBUNTU: 'linux'>)
]

Linux distributions are thought-about impartial working methods. So, Ubuntu and Debian are each impartial methods with completely different objectives and goal audiences. Nevertheless, they share a standard kernel known as Linux.

The above enumeration maps working methods to their corresponding kernels. This relationship turns DEBIAN into an alias of UBUNTU, which can be helpful when you have got code that’s kernel-related together with code that’s particular to a given Linux distribution.

An essential piece of habits to notice within the above instance is that if you iterate over the enumeration straight, aliases aren’t thought-about. In case you ever have to iterate over all of the members, together with aliases, then you want to use .__members__. You’ll be taught extra about iteration and the .__members__ attribute within the part about iterating through enumerations.

You even have the choice to fully forbid aliases in your enumerations. To do that, you need to use the @unique decorator from the enum module:

>>>

>>> from enum import Enum, distinctive

>>> @distinctive
... class OperatingSystem(Enum):
...     UBUNTU = "linux"
...     MACOS = "darwin"
...     WINDOWS = "win"
...     DEBIAN = "linux"
...
Traceback (most up-to-date name final):
    ...
ValueError: duplicate values in <enum 'OperatingSystem'>: DEBIAN -> UBUNTU

On this instance, you beautify OperatingSystem with @distinctive. If any member worth is duplicated, then you definitely get a ValueError. Right here, the exception message factors out that DEBIAN and UBUNTU share the identical worth, which isn’t allowed.





Source link

Share30Tweet19
learningcode_x1mckf

learningcode_x1mckf

Recommended For You

Build a JavaScript Front End for a Flask API – Real Python

by learningcode_x1mckf
February 1, 2023
0
Build a JavaScript Front End for a Flask API – Real Python

Most fashionable net functions are powered by a REST API below the hood. That manner, builders can separate JavaScript front-end code from the back-end logic that an online...

Read more

Using the Terminal on Linux – Real Python

by learningcode_x1mckf
January 31, 2023
0
Using the Terminal on Linux – Real Python

The terminal might be intimidating to work with once you’re used to working with graphical consumer interfaces. Nonetheless, it’s an vital device that you have to get used...

Read more

How to Iterate Over Rows in pandas, and Why You Shouldn’t – Real Python

by learningcode_x1mckf
January 30, 2023
0
How to Iterate Over Rows in pandas, and Why You Shouldn’t – Real Python

One of the crucial frequent questions you may need when coming into the world of pandas is easy methods to iterate over rows in a pandas DataFrame. In...

Read more

Orchestrating Large and Small Projects With Apache Airflow – The Real Python Podcast

by learningcode_x1mckf
January 27, 2023
0
Orchestrating Large and Small Projects With Apache Airflow – The Real Python Podcast

Jan 27, 2023 54m Have you ever labored on a mission that wanted an orchestration device? How do you outline the workflow of a complete information pipeline or...

Read more

Try Out Code and Ideas Quickly – Real Python

by learningcode_x1mckf
January 25, 2023
0
Try Out Code and Ideas Quickly – Real Python

The Python customary shell, or REPL (Learn-Eval-Print Loop), lets you run Python code interactively whereas engaged on a mission or studying the language. This instrument is on the...

Read more
Next Post
3 Reasons to Learn and 3 Not to Learn Java Programming Language

3 Reasons to Learn and 3 Not to Learn Java Programming Language

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Related News

The ultimate VIPER architecture tutorial

The ultimate VIPER architecture tutorial

October 9, 2022
The abstract Vapor service factory design pattern

The abstract Vapor service factory design pattern

February 1, 2023
Getting started with Feather CMS

Getting started with Feather CMS

September 20, 2022

Browse by Category

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

RECENT POSTS

  • Java :Full Stack Developer – Western Cape saon_careerjunctionza_state
  • Pay What You Want for this Learn to Code JavaScript Certification Bundle
  • UPB Java Jam brings coffeehouse vibes to Taylor Down Under | Culture

CATEGORIES

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

© 2022 Copyright Learning Code

No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#

© 2022 Copyright Learning Code

Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?