top of page

3 Neglected Features in Python 3 That Everyone Should Be Using

Enums, fstrings, and data classes

Python 3 has been around for a while now, and most developers — especially those picking up programming for the first time — are already using it. But while plenty of new features came out with Python 3, it seems like a lot of them are unknown or underutilized. In today’s article, I’ll talk about three lesser-known yet very useful features. They are features that I’ve come to know and love in other languages that I really think make Python 3 great.


Enums are something I’ve used in Java and Swift a lot, and my usage of them extends into Python.

Declaring an enum in Python is very easy and could also be done prior to Python 3 (albeit with more limited functionality):

from enum import Enum
class State(Enum):

myState= State. AIR
# Prints 0
# Prints AIR

In the code above, you can see an enum is easily declared by declaring a class and making it a subclass of Enum. From there, you just define each of your states in the following lines. In my case, I had AIR, LAND, and SEA available.

The functionality that was added in Python 3 is the ability to do .value and .name. Those will allow you to get the associated integer value with the state or the string associated with it. In the code above, printing will return LAND, so the functionality is more than just an integer.

Enums are useful in code when you want a descriptive representation of constants. For example, instead of checking if a state is 0 or 1, it is much better to check if it is State.MOVING or State.STATIONARY.

Your constants could change, and if someone is looking at your code, MOVING makes a lot more sense than 0. As a result, readability is greatly improved.

For more reading, check out the official Python 3 documentation on Enum here.


Added in Python 3.6, fstrings are a great way to format text. They provide much greater readability and are less error-prone (which I certainly enjoy, coming from languages like Java).

fstrings are a more readable way than the format previously used in Python. Here is an example of using format:


# Hi, my name is Brett and I am writing on my Medium blog
.a="Hi, my name is {} and I am writing on my {} blog.".format(name, blog_title)

As you can see we have empty brackets through the string and then afterwards we list out the name of each variable in order.

Now take a lot at the same code but using fstring it is much more readable, and very akin to formatting a string in Swift.


# Hi, my name is Brett and I am writing on my Medium blog
.a=f"Hi, my name is {name} and I am writing on my {blog_title} blog."

To accomplish this cleaner string, we simply preface our quotes with the letter f and then instead of having empty brackets, we put the variable or data into the brackets directly. Since the variables are written within the brackets themselves you don’t have to count the number of items written in format to figure out what variable is placed where — the variables exists right where they are going to be placed.

Doing fstrings produces much more readable and reliable code than doing something like string concatenation or format strings.

Data Classes

Data classes may be a more obscure subject than the other topics I’ve touched on, so I’ll explain them briefly. Data classes are something I’ve grown to really like in Kotlin, so I really like trying to use them in Python as well.

A data class is effectively a class whose sole purpose is to literally hold data. The class will have variables that can be accessed and written to, but there is no extra logic on top of it.

Imagine you have a program and you pass a string and an array of numbers between different classes. You could just have methods like pass(str, arr), but a much better approach would be to make a data class that only contains a string as a field and an array.

By making a data class, what you are doing will be much clearer and it will also be easier to unit test. I’ll give an example of how to make a simple data class that represents a three-dimensional vector, but this can easily be extended to represent any combination of different data:

from dataclasses import dataclass

# Define dataclass 
x: int
y: int
z: int

# Create a vector
# Outputs: Vector3D(x=1, y=1, z=-1)

Here, you can see the definition of a data class is very similar to declaring a normal class, except we use @dataclass before it and then each field is declared like name: type.

While the functionality of our created Vector3D is limited, the point of the data class is just to increase efficiency and reduce errors in your code. It’s much better to pass around a Vector3D than int variables. For more detail on @dataclass check out the official Python 3 documentation here.


If you’ve tried any of these new features let me know in a comment! I’d love to hear your different use cases for them. Happy coding!




bottom of page