есть ли у python операторы преобразования? - PullRequest
7 голосов
/ 13 июля 2009

Я так не думаю, но я подумал, что спросить на всякий случай. Например, для использования в классе, который инкапсулирует int:

i = IntContainer(3)
i + 5

И я не просто заинтересован в этом примере с int, я искал что-то чистое и общее, не перекрывающее каждый метод int и string.

Спасибо, Саньцзян. Это именно то, что я хотел. Я не осознавал, что вы можете создать подкласс этих неизменяемых типов (из C ++).

class IntContainer(int):
    def __init__(self,i):
        #do stuff here
        self.f = 4

    def MultiplyBy4(self):
        #some member function
        self *= self.f
        return self

print 3+IntContainer(3).MultiplyBy4()

Ответы [ 5 ]

11 голосов
/ 13 июля 2009

Это должно сделать то, что вам нужно:

class IntContainer(object):
    def __init__(self, x):
        self.x = x

    def __add__(self, other):
        # do some type checking on other
        return self.x + other

    def __radd__(self, other):
        # do some type checking on other
        return self.x + other

Выход:

In [6]: IntContainer(3) + 6
Out[6]: 9

In [7]: 6 + IntContainer(3)
Out[7]: 9

Для получения дополнительной информации ищите "radd" в следующих документах:

Вы найдете другие такие методы для "правильного сложения", "правильного вычитания" и т. Д.

Вот еще одна ссылка, охватывающая тех же операторов:

Кстати, в Python есть операторы приведения:

Но они не будут выполнять то, что вам нужно в вашем примере (в основном потому, что методы не имеют каких-либо аннотаций типов для параметров, поэтому нет хорошего способа неявного приведения). Так что вы можете сделать это:

class IntContainer2(object):
    def __init__(self, x):
        self.x = x

    def __int__(self):
        return self.x


ic = IntContainer2(3)
print int(ic) + 6
print 6 + int(ic)

Но это не удастся:

print ic + 6  # error: no implicit coercion
3 голосов
/ 13 июля 2009

иногда может быть достаточно просто подкласса от int напрямую. тогда __add__ и __radd__ не нужно одевать.

class IntContainer(int):
    pass
i = IntContainer(3)
print i + 5 # 8 
print 4 + i # 7

class StrContainer(str):
    pass
s = StrContainer(3)
print s + '5' # 35
print '4' + s # 43
3 голосов
/ 13 июля 2009

Вы не получите операторы преобразования, как в C ++, потому что Python не имеет такого рода строгой статической системы типов. Единственными операторами автоматического преобразования являются те, которые обрабатывают числовые значения по умолчанию (int / float); они предопределены на языке и не могут быть изменены.

Тип "преобразование" обычно выполняется конструкторами / фабриками. Затем вы можете перегрузить стандартные методы, такие как __add__, чтобы они работали как другие классы.

3 голосов
/ 13 июля 2009

Это то, что вам нужно?

In [1]: class IntContainer(object):
   ...:     def __init__(self, val):
   ...:         self.val = val
   ...:     def __add__(self, val):
   ...:         return self.val + val
   ...:     def __radd__(self, val):
   ...:         return self.val + val
   ...:
   ...:

In [2]: i = IntContainer(3)

In [3]: i + 5
Out[3]: 8

In [4]:
0 голосов
/ 22 февраля 2018

Извините, что пришли на вечеринку с опозданием на 8,5 лет. Вы можете получить из неизменяемого (например, Int). Вы не можете определить __init__, потому что неизменяемый объект уже создан и не может быть изменен (по определению). Здесь пригодится __new__.

class IntContainer(int):
   def __new__ (cls, val):
      ival = int.__new__(cls, val)
      ival._rval = 'IntContainer(%d)' % ival
      return ival
   def __repr__ (self):
      return self._rval

In [1]: i = IntContainer(3)

In [2]: i
Out[2]: IntContainer(3)

In [3]: repr(i)
Out[3]: 'IntContainer(3)'

In [4]: str(i)
Out[4]: '3'

In [5]: i + 5
Out[5]: 8

In [6]: 4 + i
Out[6]: 7

In [7]: int(i)
Out[7]: 3

In [8]: float(i)
Out[8]: 3.0

Теперь ответим на ваш вопрос об операторах конвертации. Вы также можете определить __int__, __long__, __float__ и, очевидно, __str__. Чтобы преобразовать или привести к произвольному объекту, вам, скорее всего, потребуется изменить другой объект, чтобы получить то, что вы хотите. Вы можете использовать метод __new__ этого другого объекта. Или, если другой объект уже создан, попробуйте использовать __call__.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...