-2
class MyClass():
    def __init__(self, name, high=None, low=None):
        self.name = name
        if low:
            self.low = low
        elif high:
            self.high = high
        else:
            raise Error("Not found")

    def __repr__(self):
        value = self.low or self.high
        return '{}({}, {})'.format(str(self), self.name, value)

I have a unit test case, in which MyClass is being instantiated like,

gain = MyClass('name', high='high_value')
assert isinstance(repr(gain), str)

But when my repr() is called, it is throwing AttributeError,

AttributeError: 'MyClass' has no attribute 'low'

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Pranava
  • 15
  • 4
  • 3
    You are not setting `self.low` when instantiating via `MyClass('name', high='high_value')` because the `self.low = low` line isn't reached. Why don't you get rid of the `if` checks altogether and allow `None` as the value? – timgeb Sep 30 '21 at 13:17
  • 3
    I'm not sure what is unclear to you. – mkrieger1 Sep 30 '21 at 13:17
  • Also note that `0` and `0.0` will evaluate to `False` in boolean contexts just like `None`. – timgeb Sep 30 '21 at 13:17

1 Answers1

2

I would refactor your code to the following

class MyClass:
    def __init__(self, name, high=None, low=None):
        self.name = name
        self.low = low
        self.high = high
        if self.low is None and self.high is None:
            raise Error("Not found")
        if self.low is not None and self.high is not None:
            raise Error("Only low OR high may be specified, not both")
        
    def __repr__(self):
        value = self.low if self.low is not None else self.high
        return '{}({}, {})'.format(str(self), self.name, value)

So in __init__ your assertion is that exactly one of low or high were set, in other words it is an error to have neither set or both set. Then in __repr__ you can assign value based on which was passed in. In this case both self.low and self.high will exist, though one of their values will be None.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218