can u do some logic in __init__ of a class?

Question:

okay, some background, i was mainly using imperative and functional programming for last couple of years … now i’m learning OOP and i feel that my code not following the best practices of the OOP paradigm.

class ImageBounding(Bounding):

def __init__(self, x, y, w, h, image):
    super().__init__(x, y, w, h)
    self.image = image
    img = Image.fromarray(self.image)
    self.text = pytesseract.image_to_string(img)

well i want text to be an attribute of any instance of ImageBounding but text depends on the value of the attribute image … it’s working but i feel the way i wrote this something is wrong.

please enlighten me if you know how to do this in a better way,

Asked By: youssef

||

Answers:

You can, but it might be better to minimize it. For example, the "dumbest" version of __init__ would simply take an existing image and its corresponding text. A class method could be used to encapsulate the logic that derives text from the image.

class ImageBounding(Bounding):
    
    def __init__(self, x, y, w, h, image, text):
        super().__init__(x, y, w, h)
        self.image = image
        self.text = text

    @classmethod
    def from_image(cls, x, y, w, h, image):
        text = pytesseract.image_to_string(Image.fromarray(image))
        return cls(x, y, w, h, image, text)

Note that this is similar to how Image itself is defined; Image.fromarray is (probably) a class method like

def fromarray(cls, img):
    t = do_something_with_image(img)
    return cls(t)

This allows the creation of an ImageBounding instance to be easier (and potentially cheaper) for testing, without sacrificing the ability to create a "properly" configured instance in practice.

Answered By: chepner

while this works and as an example seems fine you could do either of the following:

  1. just process the image outside of the class and pass it to the constructor afterwards or

  2. create a private method to do the processing and call it from within __init__

    class ImageBounding(Bounding):

     def __init__(self, x, y, w, h, image):
         super().__init__(x, y, w, h)
         self.image = image
         self.text = self._processed_image()
    
     def _processed_image(self)
         img = Image.fromarray(self.image)
         return pytesseract.image_to_string(img)
    
Answered By: vencaslac
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.