5 Patterns to Write Better and Clean Code in Python

I am developer from south-east asia, Singapore. I have more than 10years of development experience. In my leisure time, I like to read and write poems. I am passionate about tech and coding.
Search for a command to run...

I am developer from south-east asia, Singapore. I have more than 10years of development experience. In my leisure time, I like to read and write poems. I am passionate about tech and coding.
No comments yet. Be the first to comment.
A Decorator is a special kind of declaration that can apply to a function to enhance its functionality. This is also called known as metaprogramming.

Write clean codes using JavaScript Generators

Working with JavaScript has never been easy. You always required continuous learning and exploration of new APIs/specs. One of the toughest things

Coding for a multilingual application is always challenging. Most of the time you end up adding some third-party library. Using basic React you can...

Writing better code is always a challenge in any programming language. Before wring good code, you should have a better understanding of the programing language. Reading an entire book is time-consuming. At the same time, It will be hard to remember patterns. In this article, I will highlight a few tips and patterns to write better code in Python. I am still new to Python, So it may be the case my code will be not as performant as code from an experienced developer. You may be preparing for coding challenges for companies like Google, Facebook. To successfully pass such coding challenges, you have to solve lots of coding problems in Leetcode. In coding challenges, you have to solve multiple questions. Like Facebook ask you to solve 2 questions within 40mins. A Programing Language is not restricted to the coding challenge. You can pick any programming language to solve the problem. Whatever programming language you choose, you need some tricks and tweaks to solve problems in a limited time. This article will also help you in solving complex problems on Leetcode.
While working on problems like Two Sum, You need to iterate the list and get the index of items. You can get the index either using a counter or you can use range iterator to loop through the length of the list. You can also use enumerate to iterate an iterable object with an index.
Using range operator:
def twoSum(nums, target):
num_map = {}
for i in range(len(nums)):
if nums[i] in num_map:
return [num_map[nums[i]], i]
else:
num_map[target-nums[i]] = i
print(twoSum([2, 7, 11, 15], 9))
Using enumerate:
def twoSum(nums, target):
num_map = {}
for index, num in enumerate(nums):
if num in num_map:
return [num_map[num], index]
else:
num_map[target-num] = index
An iterable object can be iterated over using a loop. slice function returns a slice object, that can extract a sublist from an iterable object. Since a string is also an iterable object. Slicing can also be used on strings. The syntax of the slice is slice(_start_, _stop_[, _step_]).
nums = [1, 2, 3, 4, 5, 6]
name = "123456"
sslice = slice(1, 6, 2)
print(nums[slice(1, 6)]) # [1, 2, 3, 4, 5, 6]
print(nums[sslice]) # [2, 4, 6]
print(name[sslice]) # 246
`
The above code can be simplified using square brackets. You can access sublist using square brackets.
Here start, stop and steps all are optional. The default value of start, stop and steps are 0, length of an object and 1 respectively.
You can also use negative values to change the flow. To understand the negative values, Let’s take an example palindrome-number problem. There are multiple ways to solve this problem. The quick way to solve it is, Convert an integer into a string and reverse the string and compare.
class Solution:
def isPalindrome(self, x):
num1 = str(x)
num2 = num1[::-1]
return num1 == num2
print(Solution().isPalindromewithReverse(121)) # True
print(Solution().isPalindromewithReverse(-121)) # False
Here in the above example, The reverse of the string num1 is assigned to num2.
There are cases, Where you need to write recursion code. Memoization can really improve the performance of the code. Memoization is also useful to solve Dynamic Programming coding problems. Memoize can be tricky to implement. However, Using the decorator function it is too easy to implement memoize code. If you want to know more about decorators, You can read my article Validation in Python using Decorator.
To explain this topic, We will solve powx-n problem from Leetcode. In this problem, We have to implement a function that calculates x raised to the power n.
Code of Memoize Decorator:
def join(*args):
return reduce(lambda a, b: f"{a}_{b}", args)
def memoize(func):
memo = {}
def helper(*args):
key = join(*args)
if key not in memo:
memo[key] = func(*args)
return memo[key]
return helper
Now actual solution can be written as below
@memoize
def powHelper(x, n):
if n == 0:
return 1
return powHelper(x*x, n/2) if n % 2 == 0 else x * powHelper(x*x, (n-1)/2)
class Solution:
def myPow(self, x, n):
m = n
if n < 0:
m *= -1
res = powHelper(x, m)
return res if n >= 0 else 1/res
print(Solution().myPow(2, 3)) # 8
print(Solution().myPow(2, 5)) # 32
print(Solution().myPow(2, -5)) # 0.03125
To understand Varargs, Let’s take an example of a sum function. The sum is a function, which returns the summation of variable number parameters passed to the function.
def sum(*args):
res = 0
for num in args:
res += num
return res
print(sum(1, 2, 3)) # 6
print(sum(1, 2, 3, 4, 5)) # 15
Here sum function can accept variable arguments args. Since args is a tuple is an iterable object(tuple), We can also use reduce from functools. To learn more about functional programming, Read Functional Programming in Python.
# Using reduce, simplified version
from functools import reduce
def sum(*args):
return reduce(lambda a, b: a+b, args)
print(sum(1, 2, 3))
print(sum(1, 2, 3, 4, 5))
Note: In the above examples, varargs is a tuple. So we can unpack it.
def divide(*args):
num, den = args
return num/den
print(divide(10, 2))
You can also use named varargs. named varargs is a dictionary to accept multiple named arguments. Named varargs is very useful to take option dictionary.
def range(**args):
start = args["start"] if "start" in args else 0
end = args["end"] if "end" in args else 100
res = []
while start < end:
res.append(start)
start = start+1
return res
print(range(start=10, end=20)) # [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
Mapping of an iterable object is helpful to convert an iterable object. Mapping can be done using the map function.
numbers = [1, 2, 3, 4, 5]
result = map(lambda x: x*x, numbers) # return map object
print(list(result)) # need to convert to list
# Output: [1, 4, 9, 16, 25]
The above example uses a lambda function. If the function has multiple lines of statements, You can use a custom function.
numbers = [1, 2, 3, 4, 5]
def mapInt(num):
return num*num if num % 2 == 0 else num*num*num
print(list(map(mapInt, numbers)))
Mapping can be done on any iterable object including sets, lists, tuples etc.
Note: There is a better way to map an iterable object. It is called List comprehensions. List comprehension is a concise and elegant way to map an iterable object.
Celsius = [39.2, 36.5, 37.3, 37.8]
Fahrenheit = [((float(9)/5)*x + 32) for x in Celsius]
print(Fahrenheit) # [102.56, 97.7, 99.14, 100.03999999999999]
You can also map to a dictionary, set and tuple. To learn more read datastructures
>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}
In this article, I have just mentioned a few tips and patterns. There are a lot of other cool concepts to be learned. To keep the article to a concise length, I have broken this article into multiple sub-article. I will publish those later. I have attached all reference link below.