Boris Gorelik
Boris Gorelik

Reputation: 31767

How to treat an object as a numeric type in Python

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

Answers (2)

Alex Pertsev
Alex Pertsev

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

user2722968
user2722968

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

Related Questions