Reputation: 31767
I sometimes want an object to be treated as a number. This is what I do:
class C(object):
def __init__(self):
self.a = 1.23
self.b = 'b'
def __float__(self):
return float(self.a)
c = C()
Explicit casting works:
works = float(c) + 3.141
correct_comparison = (float(c) < 1)
>>> correct_comparison
False
However, automatic (implicit) casting doesn't work
wrong_comparison = (c < 1)
>>> wrong_comparison
True
doesnt_work = c + 2.718 #TypeError exception is thrown
Is there a way to perform automatic casting in Python. How bad is this idea?
UPDATE @BrenBarn has pointed me to the "emulating numeric types" section in Python documentation. Indeed, it is possible to define every possible operator, which gives a lot of flexibility, but is also very verbose. It seems that automatic implicit casting is possible only if one defines all the relevant operators. Is there a way to make this less verbose?
Upvotes: 0
Views: 1132
Reputation: 948
As @BrenBarn said, you can use inheritance:
class SomeFloat(float):
def __init__(self, *args):
super(float, self).__init__(*args)
self.b = 'b'
It will be not so verbose.
Upvotes: 3
Reputation: 16485
This is not the way Python thinks about objects. There is little value coming casting C
to a float because Python usually doesn't care what an object is but how an object behaves. You should implement the custom comparison functions like __lt__
and __eq__
. See here. This will also be handy.
The solution may look something like
import functools
@functools.total_ordering
class C(object):
def __init__(self):
self.a = 1.2345
def __float__(self):
return float(self.a)
def __eq__(self, other):
return self.a == float(other)
def __lt__(self, other):
return self.a < float(other)
c = C()
assert c < 3.14
assert 3.14 > c
assert c == 1.23456
assert 1.23456 == c
assert c != 1
Upvotes: 1