1

Is it possible to define a data object in python that behaves like a normal integer when used in mathematical operations or comparisons, but is also able to store instance variables?

In other words, it should be possible to do the following things:

pseudo_integer = PseudoInteger(5, hidden_object="Hello World!")
print(5 + pseudo_integer) # Prints "10"
print(pseudo_integer == 5) # Prints "True"
print(pseudo_integer.hidden_object) # Prints "Hello World!"
5
  • have you already tried smth? please post your tries here Commented Jan 26, 2018 at 16:03
  • So what would you expect the hidden_object to be, after a addition ? Commented Jan 26, 2018 at 16:03
  • @messerbill: I wouldn't know how to tackle the problem so I haven't tried anything. Commented Jan 26, 2018 at 16:10
  • @liliscent: There is no need to call hidden_object after an addition, so it's okay if it's gone. I just need it to either be able to be added, compared or hidden_object to be obtained. Commented Jan 26, 2018 at 16:12
  • What type do you want 5 + pseudo_integer to have? Should it have type int, or type PseudoInteger? What about pseudo_integer + pseudo_integer? Commented Jan 26, 2018 at 16:59

4 Answers 4

4

So, all answers above are fine, but probably you don't want to re-define all existing methods.

Normally, in python you can just subclass any built-in class (type). But with immutable types (and integers in python are immutable) is slightly tricky. TL;DR:

class PseudoInt(int):
    def __new__(cls, x, hidden, *args, **kwargs):
        instance = int.__new__(cls, x, *args, **kwargs)
        instance.hidden = hidden
        return instance

x = PseudoInt(5, 'secret')
x.hidden  # 'secret'
x + 4  # 9
x * 3  # 15

Normally, you should reload __init__ method, but with immutable bases you should use __new__. You can read more about data model in corresponding docs section

All this is viable only if you need single signature for constructing your object. If its fine to have 1 call for creating, and dedicated calls to populate object with attributes - Kevin's answer is all you need

Sign up to request clarification or add additional context in comments.

3 Comments

The OP will still have to override existing methods like __add__ if they want the result of PseudoInt(5) + 3 to be a PseudoInt.
True. The same applies to in-place math, like PseudoInt(5) += 4 will return 9. But I guess, this is what OP wanted - int-like object. To return same class with math ops, __ methods should be reloaded, you're right.
I'd hope that PseudoInt(5) += 4 would be a SyntaxError! </nitpick>
1

Yes, it is. You can create your own custom class. Python has many magic methods to help you archive that.

Check the code:

class PseudoInteger:
    def __init__(self, x, s):
        self.x = x
        self.s = s

    def __add__(self, num):
        return self.x + num

    def __eq__(self, num):
        return self.x == num


a = PseudoInteger(5, 'hello, world')
print(a + 3)
print(a == 5)
print(a == 2)

Or you can just inherit from int, after creating an instance, you are able to assign attributes to the inherited int object. You can't assign attributes to int directly, because int does not support item assignment :

class PseudoInteger(int):
    pass

a = PseudoInteger(5)
a.hidden = 'hello, world'

print(a)
print(a == 5)
print(a + 3)
print(a.hidden)

1 Comment

Thanks! This helps me a lot.
1

You simply need a class for this:

class PseudoInteger(object):
    def __init__(self, num, hidden=None):
        self.num = num
        self.hidden = hidden

    def __add__(self,  otherVal):
        if isinstance(otherVal, PseudoInteger):
            return self.num + otherVal.num
        else:
            return self.num + otherVal

p = PseudoInteger(4, 'Tiger')
q = PseudoInteger(6, 'lion')

print (p+q)
print (p+4)

This prints out:

10
8

You have to add the other operations (division, substraction, eq, ...) you need to the class on your own :)

3 Comments

Hi, thank you very much, this looks promising. i have one question: is this also possible without manually having to define all these methods, like add , sub, eq, gt etc? So basically that it inherits all these methods from the "original" Integer class and I just add the instance variables and methods that I need to it?
@MauriceMeyer, you're actually pointing to the post that shows how to do this, not why it's impossible ;)
0

Look into implementing the __add__ and __eq__ methods for your PseudoInteger class

1 Comment

Thanks! This helps me a lot.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.