How can I write cleanly __init__ method in python?
Question:
I want write cleanly init method in python.
my init method is very long and dirty.
I don’t know how can clean it.
and its my dirty code:
class Detect:
"""Class to show frames"""
def __init__(self,
main_target,
target_object,
camera,
sms_class,
qr_code_class,
cuda="CPU"):
self.main_target = main_target
self.target_object = target_object
self.camera = camera
self.sms_class = sms_class
self.qr_code_class = qr_code_class
self.cuda = cuda
self.classes_names = []
self.previous_time = 0
self.authorised = True
self.first_time = 0
self.first_detect_time = 0
self.color = (255, 0, 255)
self.capture = cv.VideoCapture(self.camera)
self.conf_threshold = 0.5
self.nms_threshold = 0.3
Answers:
You can place some of your attributes outside __init__
:
class Detect:
"""Class to show frames"""
classes_names = []
previous_time = 0
authorised = True
first_time = 0
first_detect_time = 0
color = (255, 0, 255)
capture = cv.VideoCapture(self.camera)
conf_threshold = 0.5
nms_threshold = 0.3
def __init__(self,
main_target,
target_object,
camera,
sms_class,
qr_code_class,
cuda="CPU"):
self.main_target = main_target
self.target_object = target_object
self.camera = camera
self.sms_class = sms_class
self.qr_code_class = qr_code_class
self.cuda = cuda
There are multiple ways to go about it, one is to define a base class and assign all those default values in the base class, and inherit Detect
from it. I’ve even further reduced the first part using **kwargs
and setattr
method:
class BaseDetect:
def __init__(self):
self.classes_names = []
self.previous_time = 0
self.authorised = True
self.first_time = 0
self.first_detect_time = 0
self.color = (255, 0, 255)
self.conf_threshold = 0.5
self.nms_threshold = 0.3
class Detect(BaseDetect):
"""Class to show frames"""
def __init__(self, cuda = "CPU", **kwargs):
self.cuda = cuda
super().__init__()
for key, value in kwargs.items():
setattr(self, key, value)
self.capture = cv.VideoCapture(self.camera)
It still has those codes of course but doesn’t the child class look much cleaner now? Also, if those values are static and not going to change, it’s just better to make them class variable, or global constants. That’s also something you can try.
They are there for some reasons right? It’s normal for your class instances to have a lot of attributes.
But if you have inheritance hierarchy in your design, you can initialize them in the parents. It’s makes the children’s __init__
cleaner.
I think you should use python dataclasses for this :
https://docs.python.org/3/library/dataclasses.html
which would result in something like this
from dataclasses import dataclass, field
from typing import List, Any, Tuple
@dataclass
class Detect:
"""Class to show frames"""
main_target: str
target_object: str
camera: str
sms_class: Any
qr_code_class: Any
cuda: str
classes_names: List = field(default_factory=list)
previous_time: int = 0
authorised: bool = True
first_time: int = 0
first_detect_time: int = 0
color: Tuple[int] = (255, 0, 255)
conf_threshold: float = 0.5
nms_threshold: float = 0.3
def __post_init__(self):
self.capture = cv.VideoCapture(self.camera)
I want write cleanly init method in python.
my init method is very long and dirty.
I don’t know how can clean it.
and its my dirty code:
class Detect:
"""Class to show frames"""
def __init__(self,
main_target,
target_object,
camera,
sms_class,
qr_code_class,
cuda="CPU"):
self.main_target = main_target
self.target_object = target_object
self.camera = camera
self.sms_class = sms_class
self.qr_code_class = qr_code_class
self.cuda = cuda
self.classes_names = []
self.previous_time = 0
self.authorised = True
self.first_time = 0
self.first_detect_time = 0
self.color = (255, 0, 255)
self.capture = cv.VideoCapture(self.camera)
self.conf_threshold = 0.5
self.nms_threshold = 0.3
You can place some of your attributes outside __init__
:
class Detect:
"""Class to show frames"""
classes_names = []
previous_time = 0
authorised = True
first_time = 0
first_detect_time = 0
color = (255, 0, 255)
capture = cv.VideoCapture(self.camera)
conf_threshold = 0.5
nms_threshold = 0.3
def __init__(self,
main_target,
target_object,
camera,
sms_class,
qr_code_class,
cuda="CPU"):
self.main_target = main_target
self.target_object = target_object
self.camera = camera
self.sms_class = sms_class
self.qr_code_class = qr_code_class
self.cuda = cuda
There are multiple ways to go about it, one is to define a base class and assign all those default values in the base class, and inherit Detect
from it. I’ve even further reduced the first part using **kwargs
and setattr
method:
class BaseDetect:
def __init__(self):
self.classes_names = []
self.previous_time = 0
self.authorised = True
self.first_time = 0
self.first_detect_time = 0
self.color = (255, 0, 255)
self.conf_threshold = 0.5
self.nms_threshold = 0.3
class Detect(BaseDetect):
"""Class to show frames"""
def __init__(self, cuda = "CPU", **kwargs):
self.cuda = cuda
super().__init__()
for key, value in kwargs.items():
setattr(self, key, value)
self.capture = cv.VideoCapture(self.camera)
It still has those codes of course but doesn’t the child class look much cleaner now? Also, if those values are static and not going to change, it’s just better to make them class variable, or global constants. That’s also something you can try.
They are there for some reasons right? It’s normal for your class instances to have a lot of attributes.
But if you have inheritance hierarchy in your design, you can initialize them in the parents. It’s makes the children’s __init__
cleaner.
I think you should use python dataclasses for this :
https://docs.python.org/3/library/dataclasses.html
which would result in something like this
from dataclasses import dataclass, field
from typing import List, Any, Tuple
@dataclass
class Detect:
"""Class to show frames"""
main_target: str
target_object: str
camera: str
sms_class: Any
qr_code_class: Any
cuda: str
classes_names: List = field(default_factory=list)
previous_time: int = 0
authorised: bool = True
first_time: int = 0
first_detect_time: int = 0
color: Tuple[int] = (255, 0, 255)
conf_threshold: float = 0.5
nms_threshold: float = 0.3
def __post_init__(self):
self.capture = cv.VideoCapture(self.camera)