16 Python Tricks To Learn Before You Write Your Next Code
Tags: beginners, python, productivity, devops
Published: 2023-03-03 17:14:03

Python is a versatile and widely-used programming language with a vast array of libraries and frameworks. However, there are some lesser-known Python coding tricks and libraries that can make your life as a developer easier and your code more efficient.

In this blog, we will explore some of these less-known Python tricks that can be incredibly useful but are not widely known. By learning and implementing these tricks, you can save time and effort in your coding and make your code more elegant and efficient. So, let’s dive in and explore these hidden gems of the Python language!

***

## 1. Ternary operator
The ternary operator is a shorthand for an if-else statement. The syntax is value_if_true if condition else value_if_false. It's a one-liner that can replace a multi-line if-else statement, making your code more concise.

```python
a = 5 
b = 10 
max = a if a > b else b  

print(max)
#10
```

The above query checks whether ‘a’ is greater than ‘b’ and returns ‘a’ if true and ‘b’ if false.

## 2. Enumerate function

The `enumerate()` function adds a counter to an iterable and returns it in a form of enumerate object. This function is useful when you want to iterate over a list and also keep track of the index.

```python
fruits = ['apple', 'banana', 'mango'] 
for index, fruit in enumerate(fruits): 
    print(index, fruit)

#0 apple
#1 banana
#2 mango
```

## 3. Zip function

The `zip()` function aggregates elements from each of the iterables and returns an iterator of tuples. This function is useful when you want to iterate over two or more lists simultaneously.

```python
list1 = [1, 2, 3] 
list2 = ['a', 'b', 'c'] 

for x, y in zip(list1, list2):
    print(x, y)

#1 a
#2 b
#3 c
```

## 4. List comprehensions

List comprehensions are a concise way to create a list from an existing list or any iterable. It’s a one-liner that can replace a for loop, making your code more efficient and readable.

```python
squared_numbers = [x**2 for x in range(1, 6)]

print(squared_numbers)
#[1, 4, 9, 16, 25]
```

## 5. Lambda functions

Lambda functions are anonymous functions that are defined using the lambda keyword. They are useful when you need to write small, one-time functions, and you don't want to use the def keyword to define a named function.

```python
add = lambda x, y: x + y 

result = add(3, 4)

print(result)
#7
```

## 6. Any and all functions

The `any()` and `all()` functions return True or False based on the truthiness of the elements in an iterable. The `any()` function returns True if any element in the iterable is true, and `all()` function returns True if all elements in the iterable are true.

```python
numbers = [1, 2, 3, 0, 4] 
result = any(numbers) #True 
result = all(numbers) # False. 0 is making it false 
```

## 7. Itertools

The itertools module provides a set of functions to work with iterators and is not widely known. Some of the functions in this module are chain, product, and permutations.


```python
import itertools 
numbers = [1, 2, 3] 
result = list(itertools.permutations(numbers)) 


#output all the permutations 
#[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
```

## 8. Generators

Generators are a type of iterable that generate values on-the-fly, instead of storing them in memory. They are defined using the yield keyword and can be used to create custom iterators.

```python
### Generators created using yield keyword 
def fibonacci_series(n):
    a, b = 0, 1
    for i in range(n):
        yield a
        a, b = b, a + b

# Driver code to check above generator function 
for number in fibonacci_series(10):
    print(number)

#0
#1
#1
#2
#3
#5
#8
#13
#21
#34
```

## 9. Decorators

Decorators are a way to modify the behavior of a function or a class. They are defined using the @ symbol and can be used to add functionality to a function, such as logging, timing, or authentication.

```python
def log_function(func):
    def wrapper(*args, **kwargs):
        print(f'Running {func.__name__}')
        result = func(*args, **kwargs)
        print(f'{func.__name__} returned {result}')
        return result
    return wrapper

@log_function
def add(x, y):
    return x + y


print(add(5,7))

#Running add
#add returned 12
#12
```

## 10. Multiple Function Arguments

In Python, you can use the * and ** operator to handle multiple function arguments. The * operator is used to pass a list of arguments as separate positional arguments, and the ** operator is used to pass a dictionary of keyword arguments.

```python
def print_arguments(*args, **kwargs):
    print(args)
    print(kwargs)

print_arguments(1, 2, 3, name='John', age=30)

#(1, 2, 3)
#{'name': 'John', 'age': 30}
```

## 11. Dynamic Importing

You can import a module dynamically using the importlib module. This can be useful when you want to import a module based on user input or configuration.

```python
import importlib

module_name = 'math'
module = importlib.import_module(module_name)
result = module.sqrt(9)
```

## 12. Dictionary Comprehensions

Dictionary comprehensions are a concise way to create a dictionary from an existing dictionary or any iterable. It’s a one-liner that can replace a for loop, making your code more efficient and readable.

```python
squared_numbers = {x: x**2 for x in range(1, 6)}
print(squared_numbers)

#{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
```

## 13. Callable Objects

In Python, anything that can be called a function is called a callable object. This includes functions, methods, classes, and even objects that define the __call__ method.

```python
class Adder:
    def __call__(self, x, y):
        return x + y

adder = Adder()
result = adder(3, 4)

print(result)
#7
```

## 14. You can separate big numbers/characters with the underscore
Big numeric numbers are hard to interpret, so python has a great capability to put underscore to make the numbers more readable.

```python
num_test = 100_345_405 # this is the number

print(num_test)

## 100345405
```

## 15. Merge 2 dictionaries quickly
We can quickly merge 2 dictionaries in python using the following piece of code.

```python
dictionary_one = {"a": 1, "b": 2}
dictionary_two = {"c": 3, "d": 4}

merged = {**dictionary_one, **dictionary_two}

print(merged)  
# {'a': 1, 'b': 2, 'c': 3, 'd': 4}
```

## 16. Lists, sets, and dictionaries are mutable
Mutable means that we can change or update the object(list, set or dictionary) without changing the pointer of the object in the memory. Let’s see it in action.

In the below example, we are updating the cities list by appending a new city. We can see that the ID (object pointer) remains the same. The same is true for the sets and dictionary

```python
cities = ["Munich", "Zurich", "London"]
print(id(cities)) # 2797174365184
cities.append("Berlin")
print(id(cities)) # 2797174365184
```
```python
####Sets 

my_set = {1, 2, 3}
print(id(my_set))  # 2797172976992
my_set.add(4)
print(id(my_set))  # 2797172976992
```
```python
###Dictionary 

thisdict = {
  "brand": "Ford",
  "model": "Mustang",
  "year": 1964
}
print(id(thisdict))  #2797174128256
thisdict["engine"] = "2500cc"
print(id(thisdict))  #2797174128256
```

***

Thanks for reading . . .
If you find my post useful, you can [follow me](https://dev.to/arslanex) 
If you want to see my latest code you can [follow me](https://github.com/Arslanex) on GitHub too.