Testing lower- and upper bound values in Python
Except under unusual circumstances, classes are things or entities -- hence the
term objects -- while functions or methods are actions or operations. You
want to name them accordingly. For that reason, Get_labels strikes me as an
oddly named class. Based on what you've shown us, I might suggest the name
Bounds as an alternative. A side benefit of that name is that it allows you
to shorten up the attribute names without loss of meaning.
A separate method for checking the basic validity of the bounds seems like
over-engineering to me -- unless the checking logic becomes much more complex
or unless it will be used elsewhere in the code. So I would just do simple
validation in __init__() in this case.
Avoid the temptation to use chatty or verbose messages in your code. It won't
help you or your users over the long run -- at least that's my experience. Keep
things direct and rigorously concise. In fact, it's often beneficial to keep
the messages very technical rather than natural in their stylistic orientation.
What I mean by that is rather than describing the problem the way one might
verbally to a human (&quot;The lower bound, which was 1000, must be less than the
upper bound, which as 125&quot;), you are often better off to describe the problem
in a formulaic, schematic, computer-like way. Among other things, that approach
allows you to adopt a conventional format for all error messages in an
application. The error message format shown in the rewrite below could be
described generically as PROBLEM: SELF. A consistent approach makes it
easier to write validation code in the first place and to maintain it over
time. Consistency also conveys professionalism to users.
Along those lines, you can often simplify the creation of such validation
messages by first defining __repr__() for your class, as illustrated below.
For the validations you have so far, a ValueError is a closer
fit than raising a general Exception. Also, you might consider checking
for other kinds of errors: for example, are bounds restricted to integers only?
If you do check for that, raise a TypeError.
Finally, a stylistic and admittedly subjective fine point. Below is a stack
trace from your code as written. We see the verbose message twice, first as an
f-string, and then with parameters filled in. What's wrong with that? Nothing
serious, but it's heavy, tedious, even lacking a certain elegance. At a
minimum, one could say that the repetition of the verbose message is mildly
distracting to the user, putting an extra increment of a visual or cognitive
burden on the user to figure out what's going on. Compare that to the stack
trace from the revised code.
# ORIGINAL.

Traceback (most recent call last):
  File &quot;bounds.py&quot;, line 19, in &lt;module&gt;
    get_labels = Get_labels(-1,25,&quot;first&quot;)
  File &quot;bounds.py&quot;, line 7, in __init__
    self.check_threshold_validity()
  File &quot;bounds.py&quot;, line 17, in check_threshold_validity
    raise Exception(f'Sorry, the lower threshold={self.lower_bound} should be larger than 0 for configuration={self.configuration_name}')
Exception: Sorry, the lower threshold=-1 should be larger than 0 for configuration=first

# REVISED.

Traceback (most recent call last):
  File &quot;bounds.py&quot;, line 72, in &lt;module&gt;
    b1 = Bounds(1000, 125, 'first')
  File &quot;bounds.py&quot;, line 67, in __init__
    raise Exception(msg)
Exception: Upper bound must be greater than lower: Bounds(1000, 125, first)

Code with some possible edits for you to consider:
class Bounds:

    def __init__(self, lower, upper, name):
        self.lower = lower
        self.upper = upper
        self.name = name

        if lower &lt;= 0 or upper &lt;= 0:
            msg = f'Bounds must be positive: {self}'
            raise ValueError(msg)

        if upper &lt;= lower:
            msg = f'Upper bound must be greater than lower: {self}'
            raise ValueError(msg)

    def __repr__(self):
        return f'Bounds({self.lower}, {self.upper}, {self.name!r})'