3

I have a class for bounding box coordinates that I would like to convert to a dataclass, but I cannot figure out how to set attributes using a class method like I would in a normal class. Here is the normal class:

class BBoxCoords:
    """Class for bounding box coordinates"""
    def __init__(self, top_left_x: float, top_left_y: float, bottom_right_x: float, bottom_right_y: float):
        self.top_left_x = top_left_x
        self.top_left_y = top_left_y
        self.bottom_right_x = bottom_right_x
        self.bottom_right_y = bottom_right_y
        self.height = self.get_height()

    def get_height(self) -> float:
        return self.bottom_right_y - self.top_left_y

and here is what I want it to do:

bb = BBoxCoords(1, 1, 5, 5)
bb.height
> 4

This is exactly what I want. I tried to do the same thing with a dataclass

from dataclasses import dataclass    

@dataclass
class BBoxCoords:
    """Class for bounding box coordinates"""
top_left_x: float
top_left_y: float
bottom_right_x: float
bottom_right_y: float
height = self.get_height()

def get_height(self) -> float:
    return self.bottom_right_y - self.top_left_y

but self isn't defined when I try to use it, so I get a NameError. What's the correct way of doing this with a dataclass? I know I could do

bb = BBoxCoords(1, 1, 5, 5)
bb.get_height()
> 4

but I would rather call an attribute than a method.

1 Answer 1

7

For this sort of thing, you need __post_init__, which will run after __init__. Also, make sure height isn't set in __init__, so:

from dataclasses import dataclass, field   

@dataclass
class BBoxCoords:
    """Class for bounding box coordinates"""
    top_left_x: float
    top_left_y: float
    bottom_right_x: float
    bottom_right_y: float
    height: float = field(init=False)

    def __post_init__(self):
        self.height = self.get_height()

    def get_height(self) -> float:
        return self.bottom_right_y - self.top_left_y

In action:

In [1]: from dataclasses import dataclass, field
   ...:
   ...: @dataclass
   ...: class BBoxCoords:
   ...:     """Class for bounding box coordinates"""
   ...:     top_left_x: float
   ...:     top_left_y: float
   ...:     bottom_right_x: float
   ...:     bottom_right_y: float
   ...:     height: float = field(init=False)
   ...:
   ...:     def __post_init__(self):
   ...:         self.height = self.get_height()
   ...:
   ...:     def get_height(self) -> float:
   ...:         return self.bottom_right_y - self.top_left_y
   ...:

In [2]: BBoxCoords(1, 1, 5, 5)
Out[2]: BBoxCoords(top_left_x=1, top_left_y=1, bottom_right_x=5, bottom_right_y=5, height=4)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.