Reputation: 1798
I have a set of functions that calculate different numeric characteristics (in example named calculate
) but some of them might not be calculate properly. After calculation result will be print in graphic user interface with string formatting. So I would like to return an object of special class that can be formatted as float but return constant value e.g. N/A (_WrongCalculationError
). Is there any magic method in Python to do so using oldstyle formatting?
class _WrongCalculationError(object):
def __??????__(self):
return "N/A"
WrongCalculationError = _WrongCalculationError()
def calculate(x, y):
if x == y:
return WrongCalculationError
else:
return x/y
def main(*args):
print("Calculation result is: %.3f" % calculate(args[0], args[1])
I read about __format__
method but I would not like to use new-style formatting because in my point of view it's too complicated and hard to read.
Upvotes: 1
Views: 155
Reputation: 122154
Short answer: You should raise
(not return
) errors, and they should inherit from Exception
:
class WrongCalculationError(Exception):
pass
def calculate(x, y):
if x == y:
raise WrongCalculationError
return x / y
Then you can handle them like:
try:
print("Calculation result is: %.3f" % calculate(args[0], args[1]))
except WrongCalculationError:
print("Oops!")
Long answer: The "magic methods" for modulo %
are __mod__
, __rmod__
and __imod__
:
>>> class Test(object):
def __mod__(self, other):
print "foo:", other
>>> t = Test()
>>> t % "bar"
foo: bar
However, this is really just a syntax hack; it only looks a bit like C-style string formatting. If you want to pass your custom object as an value
to %
(i.e. on the right-hand side) this will not work; __rmod__
is not the same:
>>> class Test(object):
def __rmod__(self, other):
raise Exception
>>> t = Test()
>>> "bar %s" % t
'bar <__main__.Test object at 0x030A0950>'
>>> "bar %f" % t
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
"bar %f" % t
TypeError: float argument required, not Test
Note that:
__rmod__
is never called; andTypeError
occurs on a '%f'
conversion specification.You can't customise C-style string formatting; the only exception is that '%s'
will call __str__
, which you can implement, but you certainly can't give a non-float
as a value for '%f'
. By comparison, you can totally mess around with str.format
:
>>> class Test(object):
def __format__(self, spec):
return "hello!"
>>> "{0:03f}".format(Test())
'hello!'
Edit: As Martijn points out in the comments you could implement __float__
to provide a value to '%f'
, but this has to return a float.
Upvotes: 3