5 Useful Things to Know in Python | by Luay Matalka | Towards Data Science

Python is one of the best programming languages to learn largely due to its simple syntax and vast versatility. However, due to the large amount of built-in features that it provides, it can be difficult to fully assimilate the particularly useful ones. In this tutorial, we will go over 5 features (including functions and expressions) that are extremely helpful to know in python.
List comprehensions allow us to create lists from other sequences in a very concise way. We usually use list comprehensions to loop through another sequence, such as a list, and either add the elements that satisfy a certain condition, or add the result of an operation applied to each element in the sequence.
[ <expression> for <name> in <iterable or sequence> ]
A list comprehension is made up of brackets, which contain an expression, followed by a for loop, and zero or more for or if clauses. This list comprehension then creates a list that contains the expression evaluated in the context of the for and if clauses that follow it.
Let’s start with a basic list comprehension that contains only an expression and a for loop to create a list, cube_list, that contains the cubes of another list, num_list:
num_list = [1,2,3,4,5]cube_list = [num**3 for num in num_list]print(cube_list)# [1,8,27,64,125]
First, we notice that we have brackets that contain an expression, num**3, followed by a for loop, for num in num_list. Within the for loop, num is the parameter name we give for the elements that we are looping over in our num_list, just like in the original for loop above. We are basically saying, take num (or the current element) from our num_list, cube it, and then add the result of that operation to our list, similar to cube_list.append(num**3). Thus we are adding the output of the expression num**3 to the list we are making as it iterates over the for loop.
List Comprehension with ConditionWe can also add a condition to our list comprehensions using an if statement after the for loop:
[ <expression> for <name> in <iterable or sequence> if <condition> ]
cubes_of_odds = [num**3 for num in num_list if num%2 != 0]print(cubes_of_odds) # [1,27,125]
Notice how we added the if statement at the end. So num**3 will only be added to our cubes_of_odds list if the current element or num is odd using the modulo operator. The modulo operator returns the remainder when num is divided by 2, which would equal zero if num is even.
For more on list comprehensions:
towardsdatascience.com
Just like we have list comprehensions in python, we also have dictionary comprehensions. We can use dictionary comprehensions in python to create dictionaries in a very concise way as well.
{ key:value for key, value in iterable or sequence }
For example, we can use a dictionary comprehension to create a dictionary that contains the counts (the number of times a number occurs) in a list:
num_list = [1,1,7,3,5,3,2,9,5,1,3,2,2,2,2,2,9]count_dict = {num:num_list.count(num) for num in num_list}print(count_dict)# {1: 3, 7: 1, 3: 3, 5: 2, 2: 6, 9: 2}
And that’s it! First, we use curly brackets to establish that we want to create a dictionary (as opposed to a list where we would use brackets). Then, as we loop over num_list, we are creating key:value pairs as follows: num:num_list.count(num), where the key is the number (or num), and its value being the count of that number in num_list.
Dictionary Comprehensions with ConditionJust like in list comprehensions, we can add a condition to our dictionary comprehensions using an if statement after the for loop.
{ key:value for key, value in iterable or sequence if <condition> }
For example, if we only want numbers with an even count in our dictionary, we can use the following code:
num_list = [1,1,7,3,5,3,2,9,5,1,3,2,2,2,2,2,9]count_dict = {num:num_list.count(num) for num in num_list if num_list.count(num)%2==0}print(count_dict)# {5: 2, 2: 6, 9: 2}
As we can see, we added an if statement after the for loop within the dictionary comprehension. If the count of the current number is even, we add the corresponding key:value pair to our dictionary. Otherwise, we don’t add that key:value pair to our dictionary.
For more on dictionary comprehensions:
towardsdatascience.com
Lambda expressions are used to create anonymous functions, or functions without a name. They are useful when we need to create a function that will only need to be used once (a throw-away function) and can be written in one line. As such, they can be very useful to use in functions that take in another function as an argument.
Lambda functions can have any number of parameters but can only have one expression. They generally have this format which yields a function object:
lambda parameters: expression
Lambda Expression with One ParameterLet’s create a lambda expression that returns the square of a number:
lambda num: num**2
And that’s it! We first start with the lambda keyword, then the parameter num, a colon, and what you want that function to return, which is num**2.
Note that this function is anonymous, or does not have a name. So we cannot invoke the function at a later point. In addition, we did not write the return keyword. Everything after the colon is part of the expression that will be returned.
If we want to assign a lambda function to a variable so that it can be invoked later, we can do so by using an assignment operator:
square = lambda num: num**2
We can then invoke or call this function the same way we would with a function that was defined with the def keyword. For example:
square(3) # will return 9 as the output
Lambda Expression with Multiple ParametersLet’s write a lambda function that has two parameters instead of just one. For example, we can write a lambda expression that returns the sum of two numbers:
lambda num1, num2: num1+num2
As we can see, if we want our function to have multiple parameters in a lambda expression, we would just separate those parameters by a comma.
Conditional Statements in Lambda ExpressionsWe can also include if else statements in lambda expressions. We would just need to make sure that it is all on one line. For example, let’s create a function that takes in two numbers and returns the greater of those numbers:
lambda num1, num2: num1 if num1>num2 else num2
Our lambda expression takes in two numbers, num1 and num2, and returns num1 if num1 is greater than num2, else, it returns num2. Obviously this function doesn’t take into account if the numbers are equal, as it will just return num2 in that case, however, we are just illustrating how we can use conditional statements within a lambda expression.
For more on lambda expressions:
towardsdatascience.com
enumerate() allows us to iterate through a sequence but it keeps track of both the element and the index.
enumerate(iterable, start=0)
The enumerate() function takes in an iterable as an argument, such as a list, string, tuple, or dictionary. In addition, it can also take in an optional argument, start, which specifies the number we want the index to start at (the default is 0).
Using the enumerate() function, we can write a for loop :
num_list= [42, 56, 39, 59, 99]for index, element in enumerate(num_list):    print(index, element)# output: 0 421 562 393 594 99
The enumerate() function returns an enumerate object, which is an iterator. As each element is accessed from this enumerate object, a tuple is returned, containing the index and element at that index: (index, element). Thus, in the above for loop, with each iteration, it is assigning the elements of this returned tuple to the index and element variables. In other words, the returned tuple is being unpacked inside the for-statement.
We can also specify starting the index at 1 by passing in 1 as the argument for the start parameter of the enumerate() function:
num_list= [42, 56, 39, 59, 99]for index, element in enumerate(num_list, start=1):    print(index, element)# output: 1 422 563 394 595 99
For more on the enumerate() function and iterators:
towardsdatascience.com
towardsdatascience.com
The zip() function is named due to its analogous mechanism as physical zippers. When you zip something, you bring both sides together. And that’s how the zip() function works! It brings elements of the same index from multiple iterable objects, such as lists, together as elements of the same tuples.
zip(*iterables)
For example, let’s say we have two lists, first_names and last_names, and we want to combine elements of the same index from both lists into a list of tuples as follows:
first_names = ['Jane', 'John', 'Jennifer']last_names = ['Doe', 'Williams', 'Smith']Desired Output:[('Jane', 'Doe'), ('John', 'Williams'), ('Jennifer', 'Smith')]
We can use python’s built-in zip() function to accomplish this:
first_names = ['Jane', 'John', 'Jennifer']last_names = ['Doe', 'Williams', 'Smith']full_names = list(zip(first_names, last_names))print(full_names)# [('Jane', 'Doe'), ('John', 'Williams'), ('Jennifer', 'Smith')]
The zip() function takes in iterables as arguments, such as lists, files, tuples, sets, etc. The zip() function will then create an iterator that aggregates elements from each of the iterables passed in. In other words, it will return an iterator of tuples, where the i-th tuple will contain the i-th element from each of the iterables passed in. This iterator will stop once the shortest input iterable has been exhausted.
Note: Since the zip() function returns an iterator, we need to use the list() function that will use this returned iterator (or zip object) to create a list. In addition, as long as the iterables passed in are ordered (sequences), then the tuples will contain elements in the same left-to-right order of the arguments passed in the zip() function.
Using the zip() Function to Unzip IterablesIn contrast to zipping, which brings things together, unzipping takes things apart. We can also use the zip() function to unzip iterable objects in python by adding the unpacking operator * as follows:
first_and_last_names = [('Jane', 'Doe'), ('John', 'Williams'), ('Jennifer', 'Smith')]first_names, last_names = zip(*first_and_last_names)first_names = list(first_names)last_names = list(last_names)print(first_names)# ['Jane', 'John', 'Jennifer']print(last_names)# ['Doe', 'Williams', 'Smith']
The unpacking operator * will unpack the first_and_last_names list of tuples into its tuples. These tuples will then be passed to the zip() function, which will take these separate iterable objects (the tuples), and combines their same-indexed elements together into tuples, making two separate tuples. Lastly, through tuple unpacking, these separated tuples will be assigned to the first_names and last_names variables. We then use the list() function to convert these tuples into lists.
For more on the zip() function and unpacking operators:
towardsdatascience.com
towardsdatascience.com
In this tutorial, we looked at 5 extremely useful features (including expressions and functions) in python. We first learned how we can use list comprehensions and dictionary comprehensions to create lists and dictionaries, respectively, in a very concise and practical manner. We then saw how to write lambda expressions with one or more parameters and conditions. Next, we looked at how we can zip iterable objects using the zip() function, and unzip iterable objects using the zip() function with the unpacking operator *. Lastly, we learned how we can use the enumerate() function to keep track of both the element and the index as we loop over an iterable object.