Search code examples
pythonclassattributescompareself

how to compare a class attribute with another attribute value in the same instance on creation and changing time inside the class


In a timeperiod the starting point has to be smaller than the endpoint. (2000 < 2020)

My goal is a python class that compares these two values on creation time or whenever one is changed to test if they are plausible. But this should take place inside the class.

I tried someting like this in different variations - with no success:

class Timeperiod:
    def __init__(self, start, end):
        self._start = start
        self._end = end

    @property
    def start(self):
        return self._start
    @start.setter
    def start(self, start):
        # if start > self._end: ### <- How to reach the 'self._end' value from here?
        #     print ('ERROR')   ### <- to throw an error.
        self._start = start

    @property
    def end(self):
        return self._end
    @end.setter
    def end(self, end):
        # if end < self._start:
        #     print ('ERROR')
        self._end = end

tp = Timeperiod(2000, 2020)
print (tp.start, '<', tp.end,': ',tp.start < tp.end) ### <- Test outside the class
tp.start = 2050
print (tp.start, '<', tp.end,': ',tp.start < tp.end)

I can easily test the values outside the class, but how to compare them inside the class?

As far as I've learned, methods like ´__gt__´ compares values of different instances, for me they seem not to be suitable in this case. I've focused myself on the setter-method but with all my attempts I got nearly every possible attribute error.

Where's the key?


Solution

  • It's not clear what your problem is. self._end is exactly how you access the end point from inside the start setter. Rather than just print an error message, though, you should raise an exception if setting a value would break the invariant self._start = self._end.

    However, if the problem you are having is ensuring that start < end is true inside __init__ as well, I would define a private method for verifying this invariant. It can then be used in __init__ as well as in both setters.

    class Timeperiod:
        def __init__(self, start, end):
            self._assert_valid_range(start, end)
            self.start = start
            self.end = end
    
        @staticmethod
        def _assert_valid_range(start, end):
            if start >= end:
                raise ValueError(f"Attempt to use start ({start}) >= end ({end})")
    
        @property
        def start(self):
            return self._start
    
        @start.setter
        def start(self, start):
            self._assert_valid_range(start, self._end)
            self._start = start
    
        @property
        def end(self):
            return self._end
    
        @end.setter
        def end(self, end):
            self._assert_valid_range(self._start, end)
            self._end = end