подклассы int для достижения представления Hex - PullRequest
2 голосов
/ 07 августа 2009

По сути, я хочу иметь доступ ко всем стандартным операторам 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 ]

7 голосов
/ 07 августа 2009

Вы должны определить __repr__ и __str__ отдельно:

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

Функция __repr__ должна (если возможно) предоставлять текст Python, который можно eval() использовать для восстановления исходного объекта. С другой стороны, __str__ может просто возвращать читаемое человеком представление объекта.

6 голосов
/ 07 августа 2009

A декоратор класса , особенно в Python 2.6 и более поздних версиях, является самым удобным способом обернуть множество методов, чтобы «вернуть экземпляр типа этого класса, а не экземпляр суперкласса», который, как указывалось другими, является ли ваша основная проблема (за исключением споров с __str__ против __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)

немного менее элегантный, но столь же эффективный; -)

Редактировать : исправлено появление в коде «обычной проблемы с областями видимости».

1 голос
/ 07 августа 2009

В ответ на ваш комментарий:

Вы можете написать миксин самостоятельно:

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__ 
1 голос
/ 07 августа 2009

Вам нужно будет получить операторы (+, -, ** и т. Д.) Для возврата экземпляров 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 ???

0 голосов
/ 07 августа 2009

Переопределить __str__, а также.

__repr__ используется при вызове repr (o) и для отображения значения в интерактивной подсказке. __str__ вызывается для большинства случаев строкового преобразования объекта, в том числе при его печати. ​​

Поведение __str__ по умолчанию для объекта заключается в использовании repr, но int предоставляет собственный метод __str__ (который идентичен __repr__ (до Python 3), но не отступить к __repr__).

...