子类化int以获得十六进制表示

时间:2009-08-07 02:24:52

标签: python hex subclassing representation

基本上我想要访问所有标准的python int运算符,例如__and____xor__等,特别是在最终打印结果时,我希望它以十六进制格式表示。 (有点像把计算器放到十六进制模式)

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

理想情况下,两行输出应为十六进制:0xfacade,但第一行输出十进制:16435934

有什么想法吗?

5 个答案:

答案 0 :(得分:7)

您应该分别定义__repr____str__

class Hex(int):
  def __repr__(self):
    return "Hex(0x%x)" % self
  def __str__(self):
    return "0x%x" % self

__repr__函数应该(如果可能)提供可以eval()重建原始对象的Python文本。另一方面,__str__只能返回对象的人类可读表示。

答案 1 :(得分:6)

类装饰器,特别是在Python 2.6及更高版本中,是包装大量方法以“返回此类类型的实例而不是超类的实例”的最方便的方法,正如其他人所指出的那样,是你的根本问题(除__str__ vs __repr__之外的狡辩,值得,但根本没有解决你的问题; - )。

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

在Python 2.6中,这会发出

0x929 0x1538 0x1c11

根据需要。当然你可以为装饰器添加更多方法名等;如果您坚持使用Python 2.5,请删除装饰行(以@开头的那个)并改为使用

class Hex(int):
  def __repr__(self): return hex(self)
  __str__ = __repr__
Hex = returnthisclassfrom('and or xor')(Hex)

螨虫不那么优雅,但同样有效; - )

修改:修复了代码中“通常的范围问题”的出现。

答案 2 :(得分:1)

你需要让运算符(+, - ,**等)返回Hex的实例。它会返回,即

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'>

因此,您可以覆盖各种运算符:

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)

我不知道这一点,我觉得必须有一个更好的方法,而不必覆盖每个运算符来返回Hex ???的实例

答案 3 :(得分:1)

回应你的评论:

你可以自己写一个Mixin:

class IntMathMixin:
    def __add__(self, other):
        return type(self)(int(self).__add__(int(other)))
    # ... analog for the others

然后像这样使用它:

class Hex(IntMathMixin, int):
    def __repr__(self):
         return "0x%x"%self
    __str__=__repr__ 

答案 4 :(得分:0)

也覆盖__str__

调用repr(o)时使用

__repr__,并在交互式提示符下显示值。大多数字符串化对象的实例都会调用__str__,包括何时打印它。

对象的默认__str__行为是回退到repr,但int提供了自己的__str__方法(与{{1}相同) (在Python 3之前),但不回退__repr__)。