问题
Basically I want to have access to all standard python int operators, eg __and__
and __xor__
etc, specifically whenever the result is finally printed I want it represented in Hex format. (Kind of like putting my calculator into Hex mode)
class Hex(int):
def __repr__(self):
return "0x%x"%self
__str__=__repr__ # this certainly helps with printing
if __name__=="__main__":
print Hex(0x1abe11ed) ^ Hex(440720179)
print Hex(Hex(0x1abe11ed) ^ Hex(440720179))
Ideally BOTH line of output should be hexadecimal: 0xfacade, however the first one yields decimal: 16435934
Any ideas?
回答1:
In response to your comment:
You could write a Mixin by yourself:
class IntMathMixin:
def __add__(self, other):
return type(self)(int(self).__add__(int(other)))
# ... analog for the others
Then use it like this:
class Hex(IntMathMixin, int):
def __repr__(self):
return "0x%x"%self
__str__=__repr__
回答2:
You should define __repr__
and __str__
separately:
class Hex(int):
def __repr__(self):
return "Hex(0x%x)" % self
def __str__(self):
return "0x%x" % self
The __repr__
function should (if possible) provide Python text that can be eval()
uated to reconstruct the original object. On the other hand, __str__
can just return a human readable representation of the object.
回答3:
A class decorator, especially in Python 2.6 and beyond, is the handiest way to wrap a lot of methods to "return an instance of this class's type rather than an instance of the superclass", which, as other have indicated, is your underlying issue (beyond quibbles with __str__
vs __repr__
, worthwhile but not at all resolutory for your problem;-).
def returnthisclassfrom(specials):
specialnames = ['__%s__' % s for s in specials.split()]
def wrapit(cls, method):
return lambda *a: cls(method(*a))
def dowrap(cls):
for n in specialnames:
method = getattr(cls, n)
setattr(cls, n, wrapit(cls, method))
return cls
return dowrap
@returnthisclassfrom('and or xor')
class Hex(int):
def __repr__(self): return hex(self)
__str__ = __repr__
a = Hex(2345)
b = Hex(5432)
print a, b, a^b
In Python 2.6, this emits
0x929 0x1538 0x1c11
as desired. Of course you can add more methodnames to the decorator, etc; if you're stuck with Python 2.5, remove the decorating line (the one starting with @
) and use instead
class Hex(int):
def __repr__(self): return hex(self)
__str__ = __repr__
Hex = returnthisclassfrom('and or xor')(Hex)
a mite less elegant, but just as effective;-)
Edit: fixed an occurence of "the usual scoping issue" in the code.
回答4:
You'll need to get the operators (+, -, ** etc) to return instances of Hex. As is, it will return ints, i.e.
class Hex(int):
def __repr__(self):
return "Hex(0x%x)" % self
def __str__(self):
return "0x%x" % self
>>> h1 = Hex(100)
>>> h2 = Hex(1000)
>>> h1
Hex(0x64)
>>> h2
Hex(0x3e8)
>>> h1+h2
1100
>>> type(h1+h2)
<type 'int'>
So, you can override the various operators:
class Hex(int):
def __repr__(self):
return "Hex(0x%x)" % self
def __str__(self):
return "0x%x" % self
def __add__(self, other):
return Hex(super(Hex, self).__add__(other))
def __sub__(self, other):
return self.__add__(-other)
def __pow__(self, power):
return Hex(super(Hex, self).__pow__(power))
def __xor__(self, other):
return Hex(super(Hex, self).__xor__(other))
>>> h1 = Hex(100)
>>> h2 = Hex(1000)
>>> h1+h2
Hex(0x44c)
>>> type(h1+h2)
<class '__main__.Hex'>
>>> h1 += h2
>>> h1
Hex(0x44c)
>>> h2 ** 2
Hex(0xf4240)
>>> Hex(0x1abe11ed) ^ Hex(440720179)
>>> Hex(0xfacade)
I don't know about this, I feel that there must be a better way without having to override every operator to return an instance of Hex
???
回答5:
Override __str__
as well.
__repr__
is used when repr(o) is called, and to display a value at the interactive prompt. __str__
is called for most instances of stringifying an object, including when it is printed.
The default __str__
behavior for an object is to fall back to the repr
, but int
provides its own __str__
method (which is identical to __repr__
(before Python 3), but does not fall back to __repr__
).
来源:https://stackoverflow.com/questions/1242589/subclassing-int-to-attain-a-hex-representation