Is it possible to define an integer-like object in

2019-08-19 04:53发布

问题:

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!"

回答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)


回答2:

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:

So, all answers above is 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 is 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



回答4:

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