Python is a great language and keeps evolving, generally for the better. If you are a Python programmer, you can make your programs more efficient by using the newer features, and reduce lines of code in the process. We also have code that helps you benchmark the code to see which one is faster.
- Advantages of One-Liners
- List Comprehension, Lambda, Map, Filter, Zip, Ternary, Enumerate, Join
- Create a list of million mumbers
- Benchmarking the "List of million numbers" code
- Lambda to return area of a square
- Map to apply int() to every string numeric item in list
- Accept multiple space-delimited numbers on the command line and convert them to integers using Map
- Filter to filter multiples of 5
- Zip to combine two lists
- Ternary operator
- Enumerate function to keep track of indices
- Join function
Advantages of One-Liners
Speed is the great advantage. The code becomes more concise and readable too, but this varies on individual. You can condense multiple lines into a single line.
In this article, we will show the traditional way first, followed by the one-liner way of doing the same thing.
List Comprehension, Lambda, Map, Filter, Zip, Ternary, Enumerate, Join
For our one-liners, we will use all of the above.
List Comprehension: A list comprehension consists of square brackets with an expression that is executed for each item in the list with a for loop that iterates over the list. There may be a condition within the list comprehension to filter the results into the returning list.
Lambda: A lambda is an anonyous function (a function without a name). You can define the functionality of this within the lambda.
Map: The map function accepts another function and a list (or iterable). The function is applied to each item of the list and return a list with the results.
Filter: The filter function is a function that returns an output list of items that return true when the function is called.
Zip: The zip function takes two lists (or iterables) and combines both of them into a single list. The resulting iterable contains a list of lists (or iterables). You can combine this through the list()
, dict()
, set()
, enumerate()
or as a tuple.
Ternary: The ternary operator is used to convert an if-else condition into a one-liner. It has limitations and can only be used for a single if-else block.
Enumerate: The enumerate function iterates over a list (or iterable) and maintains the list index as well, without the user having to manually maintain the index.
Join: The join function combines all items of a list using a common string, and returns a string with all items.
Create a list of million mumbers
Problem: Create a list of the first million numbers from 1 through 1,000,000.
Regular method:
nums = []
for i in range(1000000):
nums.append(i + 1)
We will create the one-liner, using List Comprehension.
nums = [i+1 for i in range(1000000)]
Benchmarking the "List of million numbers" code
Let us benchmark both the programs and see which one is faster and more efficient.
For benchmarking, we will use the time
module and time.perf_counter()
function.
Let us benchmark the code created with the regular method.
import time
start_time = time.perf_counter()
nums = []
for i in range(1000000):
nums.append(i + 1)
end_time = time.perf_counter()
print(f'Total Time: {round(end_time - start_time, 5)}')
OUTPUT:
Total Time: 0.12384
This program took 0.12384 seconds to run.
Now, let us benchmark the code that uses list comprehension.
million_numbers_list_comprehension.py
import time
start_time = time.perf_counter()
nums = [i+1 for i in range(1000000)]
end_time = time.perf_counter()
print(f'Total Time: {round(end_time - start_time, 5)}')
OUTPUT:
Total Time: 0.06563
Using list comprehension, this program took 0.06563 seconds to run, which is almost half the time using the regular method. Yeah, I love list comprehension!
Lambda to return area of a square
A lambda is an anonymous or nameless function that processes on input and returns the processed value.
For our example, we will write a function to return the area of a square using the math formula area = side ** 2
, given the side of the square.
Regular method:
def area_of_square(side=0):
return side ** 2
print(area_of_square(7))
We will rewrite this, using Lambda.
area_of_square = lambda x: x * x
print(area_of_square(7))
A lambda is best whenever a single expression has to be evaluated. For other purposes, a regular function is preferred.
Map to apply int() to every string numeric item in list
A map function returns a map object after applying a given function to every item in the list or iterable passed to it.
nums = ['2', '5', '9', '11']
For our example, let us replace the items in the above list nums
with 3 times the value of each item.
Regular method:
nums = ['2', '5', '9', '11']
for i in range(len(nums)):
nums[i] = int(nums[i])
print(nums)
OUTPUT:
[2, 5, 9, 11]
We will rewrite this, using the map()
method.
nums = ['2', '5', '9', '11']
nums = list(map(int, nums))
print(nums)
OUTPUT:
[2, 5, 9, 11]
Accept multiple space-delimited numbers on the command line and convert them to integers using Map
This is a practical scenario, usually applicable to those who take part in programming clubs like American Computing Science League (ACSL) or USA Computing Olympiad (USACO).
Your program accepts a single line of several numbers, each number separated by a single space. You end up converting each of those string-numbers from strings to integers (or floats).
Step 1: This is code that would accept the numbers as a string using input()
, split them using split()
and create a list of string-numbers.
nums = input().split()
print(nums)
INPUT:
23 56 38 21 28
OUTPUT:
['23', '56', '38', '21', '28']
Step 2: We will apply the map function with int
to the list nums.
print(map(int, nums))
<map object at 0x10bc37fd0>
This returns a map
object. We want a list object.
Step 3: We will enclose it with the list()
function to force it into a list object.
print(list(map(int, nums)))
OUTPUT:
[23, 56, 38, 21, 28]
Combining all the above steps, this is the complete code:
nums = list(map(int, input().split()))
INPUT:
23 56 38 21 28
OUTPUT:
23 56 38 21 28
Filter to filter multiples of 5
The filter function is used to filter a sequence using a function to find if each item is true or not.
For our example, let us first create a list of 100 numbers.
nums = list(range(1,101))
print(nums)
OUTPUT:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
We will filter nums
to only include multiples of 5. We will write a function is_multiple_of_5()
for this.
def is_multiple_of_5(n):
if n % 5 == 0:
return True
return False
nums = list(filter(is_multiple_of_5, nums))
print(nums)
OUTPUT:
[5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
This one-liner list(filter(is_multiple_of_5, nums))
essentially applied the filter through nums and passed each value of nums through the function is_multiple_of_5()
. This returned a filter object, and we ran it through the list()
function to create a list out of the filter object.
Zip to combine two lists
The zip()
function is used to combine two lists or iterables.
We will combine the two lists fruits
and prices
and combine them using zip()
and create a new list fruit_prices
that contain a list of tuples of each fruit matched to its price, following the sequence.
fruits = ['apples', 'mangoes', 'bananas']
prices = [15.50, 3, 7.5]
fruit_prices = list(zip(fruits, prices))
print(fruits)
print(prices)
print(fruit_prices)
OUTPUT:
['apples', 'mangoes', 'bananas']
[15.5, 3, 7.5]
[('apples', 15.5), ('mangoes', 3), ('bananas', 7.5)]
As you can see, the zip function created a tuple with the first items in each list, followed by a second tuple with the second items in each list, and so on.
[('apples', 15.5), ('mangoes', 3), ('bananas', 7.5)]
What if the lists have different sizes?
If we have lists with varying sizes, the zip function will ignore the extra items in the larger list. For example:
fruits = ['apples', 'mangoes', 'bananas']
prices = [15.5, 3, 7.5, 3.25, 8.45]
fruit_prices = list(zip(fruits, prices))
print(fruit_prices)
OUTPUT:
[('apples', 15.5), ('mangoes', 3), ('bananas', 7.5)]
The length of the smaller list fruits
is 3. So, the zip function ignored all the items in list prices
after the third item.
Ternary operator
If we have an if-else condition like this:
x = 5
if x < 7:
print('Below 7')
elif x > 7:
print('Above 7')
else:
print('Lucky 7')
We can write a one-liner for this block:
x = 5
print('Below 7' if x < 7 else 'Above 7' if x > 7 else 'Lucky 7')
This is called Ternary operator.
There are limitations to this. You cannot use ternary operators if there are multiple if-else blocks.
Ternary operators have a lot more options than just this. I will dedicate a separate blog post just for Ternary operators.
Enumerate function to keep track of indices
The enumerate function tracks an iterator while keeping track of the indices too. This helps us skip the part where we have to manually maintain a separate variable for keeping track of the index.
For our example, let us create a list planets
.
planets = ['mercury', 'venus', 'earth', 'mars', 'jupiter', 'saturn', 'uranus', 'neptune']
We want to iterate through planets
and also keep track of the list index. This is where we use enumerate()
.
In this code, we will create a variable planet_positions
that contain a list of tuples. Each tuple contains the planet position number (index + 1) and the planet name.
planet_positions = [(indx+1, planet) for indx, planet in enumerate(planets)]
print(planet_positions)
OUTPUT:
[(1, 'mercury'), (2, 'venus'), (3, 'earth'), (4, 'mars'), (5, 'jupiter'), (6, 'saturn'), (7, 'uranus'), (8, 'neptune')]
Join function
The join function is used to create a string from a list using a common delimiter.
For our example, let us create a string solar_system
which contains the names of the planets separated by *
.
planets = ['mercury', 'venus', 'earth', 'mars', 'jupiter', 'saturn', 'uranus', 'neptune']
Regular method:
solar_system = ''
for planet in planets:
solar_system += planet + '*'
solar_system = solar_system.rstrip('*') # to remove the last character, which is a *
print(solar_system)
Using the join function:
solar_system = '*'.join(planets)
print(solar_system)
OUTPUT:
mercury*venus*earth*mars*jupiter*saturn*uranus*neptune
Related Posts
If you have any questions, please contact me at arulbOsutkNiqlzziyties@gNqmaizl.bkcom. You can also post questions in our Facebook group. Thank you.