Useful tips for working with Python

Python is a popular and widely used programming language. It is used for data science and machine learning, scientific calculations in various fields, server web development, mobile and desktop applications, and so on. 

Python is used by many popular companies: Google, Dropbox, Facebook, Mozilla, IBM, Quora, Amazon, Spotify, NASA, Netflix, Reddit, and many others. 
Its syntax is developed with simplicity, readability, and elegance. 
In this article, useful tips for working with Python are represented.

The Zen of Python. 
The Zen of Python, aka PEP 20, is a small text, written by Tim Peters. This is a guideline for developing with and using Python. It may be found on the Python website. Besides, you can get it from your console or Jupyter Notebook using one statement: 

>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Chained Assignment. 
In case you need several variables to be linked to one certain object, you can use the chained assignment: 

>>> x = y = z = 2
>>> x, y, z
(2, 2, 2)

Chained Comparison. 
You can combine several comparisons into one Python expression by combining comparison operators. This expression returns True in case all the comparisons are correct, or False otherwise: 

>>> x = 5
>>> 2 < x ≤ 8
True
>>> 6 < x ≤ 8
False

It is similar to (2 <x) и (x ≤ 8) и (6 <x) и (x ≤ 8), but is more dense and requires x to be evaluated just once. 
This is also legal:

>>> 2 < x > 4
True

You can combine more than two comparisons.

>>> x = 2
>>> y = 8
>>> 0 < x < 4 < y < 16
True

Multiple Assignment.
You can assign several variables in one expression, using tuple unpacking. 

>>> x, y, z = 2, 4, 8
>>> x
2
>>> y
4
>>> z
8

Note that 2, 4, 8 in the first statement is a tuple, which is equal to (2, 4, 8).

Extended Multiple Assignment. 
Simple multiple assignments are not the only things Python is capable of. You don’t need an equal amount of elements on the left and right sides: 

>>> x, *y, z = 2, 4, 8, 16
>>> x
2
>>> y
[4, 8]
>>> z
16

In this case, x takes the first value, because it comes first. z is the last, so it takes the last value (8). As y has an asterisk, it takes all other values, which are packed up into the list. 

Swap Variables. 
You can use several assignments to swap any two variables in a concise manner, not putting in the third one:

>>> x, y = 2, 8
>>> x
2
>>> y
8
>>> x, y = y, x
>>> x
8
>>> y 2

Dicts Merge. 
One of the ways of combining two or more dicts  is unpacking them into a new file: 

>>> x = {'u': 1}
>>> y = {'v': 2}
>>> z = {**x, **y, 'w': 4}
>>> z
{'u': 1, 'v': 2, 'w': 4}

Combining Strings. 
If you join several strings, there will be the same symbol or a group of symbols appearing in between them. You can use str.join () method: 

>>> x = ['u', 'v', 'w']
>>> y = '-*-'.join(x)
>>> y
'u-*-v-*-w'

Advance Iteration.
If you want to iterate through a sequence and you need both the sequence elements and  corresponding indices, you should use enumerate: 

>>> for i, item in enumerate(['u', 'v', 'w']):
... print('index:', i, 'element:', item)
...
index: 0 element: u
index: 1 element: v
index: 2 element: w

You will get a tuple with an index and a corresponding sequence for each iteration.

Backward Iteration. 
If you want to iterate a sequence in a backward order, you should use reversed:

>>> for item in reversed(['u', 'v', 'w']):
... print(item)
...
w
v
u

Aggregate Elements. 
If you need to join the elements of several sequences, you should use zip: 

>>> x = [1, 2, 4]
>>> y = ('u', 'v', 'w')
>>> z = zip(x, y)
>>> z

>>> list(z)
[(1, 'u'), (2, 'v'), (4, 'w')]

Matrices Transpose. 
Despite people mostly use NumPy (or similar libraries) while working with matrices, you can get matrix transpose using zip: 

>>> x = [(1, 2, 4), ('u', 'v', 'w')]
>>> y = zip(*x)
>>> z = list(y)
>>> z
[(1, 'u'), (2, 'v'), (4, 'w')]

Unique Values. 
You can remove the duplicates from a receiving unique values list by converting it into a set. Do that if the order is not important.

>>> x = [1, 2, 1, 4, 8]
>>> y = set(x)
>>> y
{8, 1, 2, 4}
>>> z = list(y)
>>> z
[8, 1, 2, 4]

Sequence Sorting
By default, the sequences are sorted by their first elements.

>>> x = (1, 'v')
>>> y = (4, 'u')
>>> z = (2, 'w')
>>> sorted([x, y, z])
[(1, 'v'), (2, 'w'), (4, 'u')]

However, in case you want to sort it out by the second (or any other) elements, you can use a parameter key  and appropriate lambda function as an appropriate argument: 

>>> sorted([x, y, z], key=lambda item: item[1])
[(4, 'u'), (1, 'v'), (2, 'w')]

It looks similar when you try to get a reverse order: 

>>> sorted([x, y, z], key=lambda item: item[1], reverse=True)
[(2, 'w'), (1, 'v'), (4, 'u')]

Dicts sorting. 
You can use a similar approach to sort key-value tuples of dicts received using .items ():

>>> x = {'u': 4, 'w': 2, 'v': 1}
>>> sorted(x.items())
[('u', 4), ('v', 1), ('w', 2)]

They are sorted with keys. If you want it to be sorted by its values, you should use reverse values corresponding to the key: 

>>> sorted(x.items(), key=lambda item: item[1])
[('v', 1), ('w', 2), ('u', 4)]
>>> sorted(x.items(), key=lambda item: item[1], reverse=True)
[('u', 4), ('w', 2), ('v', 1)]

Raw formatted f-strings.
PEP 498 and Python 3.6 introduced so-called formatted strings or f-strings. You can put expressions into such strings. A string can be considered both unprocessed and formatted. 

>>> fr'u \ n v w={2 + 8}'
'u \\ n v w=10'

Retrieve Current Date and Time. 
Python has an inbuilt datetime module, which is common for working with dates and times. One of its methods, .now (), returns the current date and time: 

>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2019, 5, 20, 1, 12, 31, 230217)

Retrieve Maximal (or Minimal) Element Index. 
Python has no direct way for retrieving maximal or minimal element index in a list or a tuple. Fortunately, there are (at least) two ways of doing this: 

>>> x = [2, 1, 4, 16, 8]
>>> max((item, i) for i, item in enumerate(x))[1]
3

In case there are two or more maximal value elements, the approach returns an index of the last one: 

>>> y = [2, 1, 4, 8, 8]
>>> max((item, i) for i, item in enumerate(y))[1]
4

To get an index of the first case, you have to slightly change the previous statement: 

>>> -max((item, -i) for i, item in enumerate(y))[1]
3

An alternative way, probably, more trim one: 

>>> x = [2, 1, 4, 16, 8]
>>> max(range(len(x)), key=lambda i: x[i])
3
>>> y = [2, 1, 4, 8, 8]
>>> max(range(len(y)), key=lambda i: x[i])
3

To find an index of a minimal element, replace the max function with min. 

Retrieve Cartesian Product.
The itertools inbuilt module is a variety of potentially useful classes. One of them is a product, which is used for cartesian product retrieving:

>>> import itertools
>>> x, y, z = (2, 8), ['u', 'v', 'w'], {True, False}
>>> list(itertools.product(x, y, z))
[(2, 'u', False), (2, 'u', True), (2, 'v', False), (2, 'v', True),
(2, 'w', False), (2, 'w', True), (8, 'u', False), (8, 'u', True),
(8, 'v', False), (8, 'v', True), (8, 'w', False), (8, 'w', True)]

Matrices Multiplier Operator. 
PEP 465 and Python 3.5 introduced a special infix operator for @ matrices multiplying. This can be done for a class via using matmul, rmatmul, and imatmul methods. That’s the way the code for matrices and vectors multiplying looks like:

>>> import numpy as np
>>> x, y = np.array([1, 3, 5]), np.array([2, 4, 6])
>>> z = x @ y
>>> z
44

We’ve shown Python tips and tricks that make it interesting and elegant, but there are many other languages features worth learning.
Happy coding!