After writing nearly 20 articles just about Python, I’ve decided to take some time to reflect on what I’ve learned. For instance, I recently wrote a compilation article which includes 70+ Python code snippets. Now, I’ve put together a list of some of the coolest Python programming language features.
Coolest Python Features List
And without further ado, let’s take a look at some of the coolest Python features. If you think I’ve missed any, feel free to drop them in the comments.
List Comprehensions
By far, my favorite feature in Python is the list comprehension. Honestly, the feature isn’t all that interesting; it’s just a convenient way to generate lists. That said, it’s a feature that I haven’t seen in any other popular language (e.g. Java, C, C++, etc.). As a result, I make sure to take advantage of it as often as possible. Here are a few examples:
# Generates a list containing values from 0 to 9
[i for i in range(10)]
# Generates a list of all even values from 0 to 9
[i for i range(10) if i % 2 == 0]
# Generates a list containing values from 1 to 10
[i + 1 for i in range(10)]
# Generates a list containing values from 0 to -9
[-i for i in range(10)]
# Generates all possible pairs between 0 and 9
[(a, b) for a in range(10) for b in range(10)]
# Shallow copies another list
my_list = [1, 3, 5, 7, 9]
[item for item in my_list]
Since a list comprehension creates a list, we’re able to work with the output like any other list:
# Generates a list containing values from 0 to 9
nums = [i for i in range(10)]
nums[0] # returns 0
nums[1] # returns 1
If you’re interested in learning how to write these yourself, I have an article just for you. In it, you’ll learn more about the syntax as well as a few application areas. If you have any of your own examples, feel free to share them in the comments.
Generator Expressions
One of the nice things about learning the list comprehension syntax is that it allows you to also write generator expressions. After all, they’re very similar—one just saves you space. That’s right! Generator expressions don’t actually create lists. Instead, they provide the means for generating one item at a time of a list without ever constructing that list. Take a look:
# Generates values from 0 to 9
(i for i in range(10)])
# Generates values from 0 to 9
(i for i range(10) if i % 2 == 0)
# Generates values from 1 to 10
(i + 1 for i in range(10)])
# Generates values from 0 to -9
(-i for i in range(10))
# Generates all possible pairs between 0 and 9
((a, b) for a in range(10) for b in range(10))
# Generates a shallow copy of another list
my_list = [1, 3, 5, 7, 9]
(item for item in my_list)
Notice how similar the syntax is to the list comprehension. However, the application is slightly different. Instead of indexing the elements, we have to use a special function:
# Generates values from 0 to 9
nums = (i for i in range(10)])
next(num) # returns 0
next(num) # returns 1
Since a generator is an iterable, we can also get away with using the for loop syntax:
# Generates values from 0 to 9
nums = (i for i in range(10)])
for num in nums:
print(num) # prints each item in the generator
Once we’ve exhausted every element, the generator expression becomes useless. In other words, we can only generate every element once. After that, we have to write the expression again.
Slice Assignment
Have you ever wanted to replace entire sections of a list? Well, Python has a feature that allows you to do just that in a single line: slice assignment. Like slicing, slice assignment allows you to specify a region of a list. Of course, the difference is that slice assignment then lets you replace that region with whatever you want:
my_list = [1, 2, 3]
# Appending a list with slice assignment
my_list[len(my_list):] = [4]
# Prepending a list with slice assignment
my_list[:0] = [0]
# Replacing middle element
midpoint = len(my_list) // 2
my_list[midpoint: midpoint + 1] = [-2]
# Replacing arbitrary subsection
my_list[:2] = [3, 4, 5]
As I’ve mentioned in a related article, slice assignment doesn’t stop there. We can use any iterable on the right side. For example, we could use strings, tuples, list comprehensions, or even generator expressions. In other words, our previous two features can make an appearance:
my_list = [1, 2, 3]
my_list[len(my_list):] = (item for item in range(5))
Since learning about slice assignment in late 2019, I’ve been obsessed with it. As a result, I think it’s my second favorite feature right behind list comprehensions. Right now, I don’t have an article covering this feature in more detail, so you’re welcome to share some of your favorite examples in the comments.
Iterable Unpacking (aka Destructuring)
If you’ve checked out my article on getting the last item of a list, you might recall that iterable unpacking was one of the solutions. The idea being that we can split a list into two pieces: the last item and everything else:
my_list = [1, 2, 3]
*remainder, last_item = my_list
Well, iterable unpacking can do more than retrieve the end of a list. For example, it can be used to swap variables:
a = 1
b = 2
b, a = a, b
Normally, we’d need three lines of code to perform a swap: one to create a temporary variable, another to overwrite one of the variables, and the last to copy the temporary variable to the other variable. With iterable unpacking, it’s a single line of code.
If iterable unpacking looks familiar to you, you might know it from its other name: destructuring. Oddly enough, I featured destructuring in an article covering some of my favorite features of any programming language.
That said, I don’t use iterable unpacking very often. If you have any good examples that would supplement this list, feel free to share them.
Negative Indexing
Of all the features on this list, negative indexing is perhaps the most subtle. After all, many modern programming languages have some form of list indexing. However, few have a way of getting the last element of a list so elegantly:
my_list = [1, 2, 3]
last_item = my_list[-1]
In addition to being able to access list elements in reverse, we can also use negative indexing with list methods like insert()
, pop()
, and index()
:
my_list = ['h', 'e', 'l', 'l', 'o']
my_list.insert(-1, 'l') # ['h', 'e', 'l', 'l', 'l', 'o']
my_list.pop(-2) # ['h', 'e', 'l', 'l', 'o']
my_list.index('l', -2) # 3
If you like negative indexing, you’ll be happy to know this feature doesn’t stop with lists. Feel free to use it with strings, tuples, and other sequences.
Dictionary Comprehensions
Previously in this list, I mentioned list comprehensions. Apparently, that feature is so good that the developers decided to expand its capabilities to encompass other data structures like dictionaries. After all, wouldn’t it be nice to be able to generate a dictionary in a single line of code? Well, as of PEP 274, you can:
# Generates a dictionary of numbers to letters
{num: chr(65 + num) for num in range(5)}
# Generates the same thing
nums = [1, 2, 3, 4, 5]
letters = ["A", "B", "C", "D", "E"]
{num: letter for num, letter in zip(nums, letters)}
Typically, I use a dictionary comprehension to merge two lists into a dictionary. That said, I’m sure there are other use cases. Feel free to share some of your favorite it in the comments.
Chaining Comparisons
In many modern programming languages, comparing values is a simple process. For example, in Java, I can compare two numbers as follows:
17 > 5
In this example, the result is a boolean, true
. As a result, the following expression is illegal in Java:
17 > 5 > 1
Here, 17 > 5
evaluates to true. Then, the expression true > 1
is evaluated. Since this is nonsensical, the compiler crashes.
In Python, however, we can chain comparisons without any risks. In other words, the same expression above is perfectly valid, and it returns True
.
Under the hood, each comparison is computed just like Java. However, each intermediate result is ANDed with the result of the other comparison. For example, 17 > 5
returns True
. Then, 5 > 1
returns True. Finally, the results are combined by and
which returns True
.
Personally, I haven’t used this feature much, but it’s gotten a lot of attention on the development end. For example, PEP 535 mentions a few updates to the chaining protocol. If you know of any cool use cases for this feature, let me know in the comments.
f-Strings
Finally, we come to one of my favorite “new” (PEP 498) Python features, f-Strings. Normally, when we create strings for debugging, we lazily print them with concatenation. If we’re clever, we might use some of the string formatting techniques. Now, we can get the best of both worlds with f-Strings:
age = 25
name = 'Jeremy'
print(f'My name is {name}, and I am {age}')
In this example, we’ve created a string from two variables: name
and age
. All we had to do was prepend our string with an f
. Then, we can place any expression we want in braces, and it will be interpreted. For example, age
is a number which is automatically converted to its string representation.
I really love this f-String syntax because it solves a lot of common string formatting issues. For example, it makes string formatting very easy to read (unlike concatenation). Likewise, it makes it obvious what the output string will look like (again, unlike concatenation). Finally, there’s no issues with positioning of variables (unlike string interpolation). What you see is what you get.
While f-Strings are really helpful, I don’t find myself using them beyond debugging. Do you have any examples you’d like to share?
Honorable Mentions
As someone who really loves working with Python, I had a hard time keeping this list short. As a result, here are a few additional features that didn’t make the cut:
- For/Else loops
- Imaginary numbers
- Any() and All()
- Returning multiple values (tuples)
- Arbitrarily large integers
- Keyword arguments
- Sets
- Joining strings
- Multiplying strings
- Walrus operator
- String interpolation
- Slicing
Of course, with how enormous the standard library is in Python, I’m sure there are even more clever bits of syntax. In addition, Python development is very active, so I wouldn’t be surprised to see even more features in the future. Perhaps I’ll update this list from time to time as new features appear.
Recommendations
With all that said, thanks for sticking around to check out this list. Over the next couple months, I’ll be focusing more on Python and Git content, so expect to see more articles like this in the future. If there’s anything you’d like to see, drop a note in the comments or feel free to contact me directly.
In the meantime, support this website by hopping on the mailing list, becoming a patron, or exploring the shop. Otherwise, keep browsing the following related articles:
- The Coolest Programming Language Features
- How to Convert Two Lists to a Dictionary in Python
- How to Format a String in Python
Otherwise, thanks again for your time. I appreciate it!
The post 8 Coolest Python Programming Language Features appeared first on The Renegade Coder.
Top comments (8)
Thanks for a nice post. I had never heard about the chaining comparison. I love it!
A note on the dictionary compression.
If you just want to combine to lists to a dictionary you could also use:
Where I think the dictionary compression really shines is if you need to do some filtering when creating the dictionary
I also use dictionary compressions when mapping from a 2D arrays where I want the key to be the value of one of the columns.
Awesome post! I really love Python. But, sometimes there are just too many awesome features in your code that make it not so awesome anymore.
To fight this I recommend using wemake-python-styleguide: it is a tool to help you to write beautiful, meaningful, simple, and working Python.
Check it out, if you love elegant code!
wemake-services / wemake-python-styleguide
The strictest and most opinionated python linter ever!
wemake-python-styleguide
Welcome to the strictest and most opinionated python linter ever.
wemake-python-styleguide
is actually a flake8 plugin with some other plugins as dependencies.Quickstart
You will also need to create a
setup.cfg
file with the configuration.We highly recommend to also use:
Running
This app is still just good old
flake8
And it won't change your existing workflow.See "Usage" section in the docs for examples and integrations.
We also support Github Actions as first class-citizens Try it out!
What we are about
The ultimate goal of this project is to make all people write exactly the same
python
code.Negative indexing is great. Not only for the -1: give me the last item, but also for -2: give me the second to last value. Also: it auto-wraps around. List of length 3? Index -4 brings you right back to the end. Great alternative for % (modulo) indexing and/or itertools.cycle. Be careful though, it might not make your code more readable, so be sure to express intent
Good post! My favorites are list comprehensions and f-strings.
It seems the language has a lot of cool stuff in it. My only worry is that these features will increase the complexity of the language rather than improving it, but I haven't really seen that yet!
Some comments may only be visible to logged-in visitors. Sign in to view all comments.