Проблема:
Я реализовал класс с довольно сложным внутренним поведением, который притворяется типом int
во всех смыслах и целях. Затем, в качестве вишенки на торте, я действительно хотел, чтобы мой класс успешно прошел проверки isinstance() и issubclass() для int
. Я потерпел неудачу до сих пор.
Вот небольшой демонстрационный класс, который я использую для проверки концепции. Я пытался наследовать его как от object
, так и от int
, и, хотя он наследуется от int
, он проходит проверки, но также нарушает его поведение:
#class DemoClass(int):
class DemoClass(object):
_value = 0
def __init__(self, value = 0):
print 'init() called'
self._value = value
def __int__(self):
print 'int() called'
return self._value + 2
def __index__(self):
print 'index() called'
return self._value + 2
def __str__(self):
print 'str() called'
return str(self._value + 2)
def __repr__(self):
print 'repr() called'
return '%s(%d)' % (type(self).__name__, self._value)
# overrides for other magic methods skipped as irrelevant
a = DemoClass(3)
print a # uses __str__() in both cases
print int(a) # uses __int__() in both cases
print '%d' % a # __int__() is only called when inheriting from object
rng = range(10)
print rng[a] # __index__() is only called when inheriting from object
print isinstance(a, int)
print issubclass(DemoClass, int)
По сути, наследование от неизменяемого класса приводит к неизменяемому классу, и Python часто будет использовать необработанное значение базового класса вместо моих тщательно разработанных магических методов. Нехорошо.
Я смотрел на абстрактные базовые классы, но они, кажется, делают что-то совершенно противоположное: вместо того, чтобы сделать мой класс похожим на подкласс встроенного типа, они заставляют класс притворяться надклассом по отношению к нему.
Использование __new__(cls, ...)
тоже не похоже на решение. Хорошо, если все, что вам нужно, это изменить начальное значение объекта перед его фактическим созданием, но я хочу уклониться от проклятия неизменности. Попытка использовать object.__new__()
тоже не принесла результатов, так как Python просто пожаловался, что использовать object.__new__
для создания объекта int
небезопасно.
Попытка унаследовать мой класс от (int, dict) и использовать dict.__new__()
также не увенчалась успехом, так как Python явно не позволяет объединить их в один класс.
Я подозреваю, что решение может быть найдено с помощью метаклассов, но с ними пока тоже не получилось, в основном потому, что мои мозги просто недостаточно согнуты, чтобы правильно их понять. Я все еще пытаюсь, но не похоже, что я скоро получу результаты.
Итак, вопрос: возможно ли вообще наследовать или имитировать наследование от неизменяемого типа, даже если мой класс очень изменчив? Структура наследования классов для меня не имеет большого значения, пока найдено решение (при условии, что оно вообще существует).
_value
, когда экземпляры ваших классов являются самиint
? - person GingerPlusPlus   schedule 10.12.2015int
заменены экземплярами моего класса псевдо-int, который необходим для получения некоторых интересных блестящих функций. И было бы очень хорошо, если бы по крайней мереisinstance()
проверки были успешными, если они происходят в стороннем коде, так как это уменьшает количество изменений, которые я должен попросить сделать других ребят. - person Lav   schedule 10.12.2015_value
, потому чтоisinstance(self, int)
. Вместо того, чтобы делатьself._value + anything
, вы можете просто сделатьsuper().__add__(anything)
. - person GingerPlusPlus   schedule 10.12.2015_value + 2
предназначен только для динамической оценки. - person Lav   schedule 10.12.2015