Low Level Design in a Dynamically Typed Language
Java is often preferred for practicing LLD (Low Level Design) due to its strong typing. But I like a challenge and I choose Python.
I have tried to solve LLD problems using both Python and Java and I can say that Python is clearly harder to use, objectively speaking. Contrary to what I was expecting, Python requires more or less the same LoC (Lines of Code) as Java, it does not enforce type safety, and it is harder to debug. This article contains some tricks I have learned while practicing LLD in Python.
Thread Safety
Python is not thread-safe by default. You can use the threading
module to create threads and synchronize them using locks. If you have used synchronized
in Java, then this would make a lot of sense to you.
I usually have a decorator that I use to synchronize methods in Python. Here is an example:
1
2
3
4
5
6
7
8
9
10
def synchronized(lock):
# 'synchronized' decorator that mimics Java's synchronized keyword
def decorator(func):
def wrapper(*args, **kwargs):
with lock:
return func(*args, **kwargs)
return wrapper
return decorator
Property Decorators for Getters and Setters
Unlike Java, Python does not have the concept of getters and setters. You can use the @property
decorator to create getters and setters. An underscore _
before an instance attribute means that it is not public (not supposed to be accessed outside the class). Here is an example:
This is important for LLD interviews.
1
2
3
4
5
6
7
8
9
10
11
12
class Person:
def __init__(self, first_name, last_name):
self._first_name = first_name
self._last_name = last_name
@property
def first_name(self):
return self._first_name
@first_name.setter
def first_name(self, value):
self._first_name = value
Custom Exceptions
In Python, you can create custom exceptions by inheriting from the Exception
class. This is similar to creating custom exceptions in Java by extending the Exception
class. This is again, important for LLD interviews.
1
2
3
4
class ParkingLotException(Exception):
def __init__(self, message: str):
self.message = message
super().__init__(self.message)
Unlike in Java, interfaces and abstract classes are not strictly enforced in Python. However, the abc
module can be used to create abstract classes and abstract methods, which can be used to enforce the implementation of certain methods in subclasses.