2010-11-29 3 views
1

Я понимаю концепцию изменчивых v. Неизменяемых объектов в Python, без проблем. Хотя внутренняя ценность любого неизменяемого объекта не может быть изменена напрямую, любой экземпляр неизменяемого объекта может быть переустановлен с разными значениями. То, что я хотел бы сделать, это построить внутреннюю функцию в подклассе кортежа, который может контролироваться, переназначить его собственную ценность. Это может быть базовая функциональность, которую я просто не могу найти и буду признателен за любую помощь.Python subclass tuple object с возможностью восстановления себя внутри

Например, вот что я хотел бы сделать, но это, очевидно, не работает.

class myTuple(tuple): 
    def __new__(self): 
     initialValue = [1, 2, 3] 
     return super(myTuple, self).__new__(self, initialValue) 
    def resetMyself(self): 
     newValue = [4, 5, 6] 
     self = tuple(newValue) 

со следующими результатами ...

>>> foo = myTuple() 
>>> print foo 
(1, 2, 3) 
>>> foo.resetMyself() 
>>> print foo 
(4, 5, 6) 

От чтения большего количества ответов на подобные вопросы на этом сайте, я знаю, что некоторые из вас могут иметь тенденцию реагировать с «Почему ты хочешь это сделать? но давайте сохраним пространство ответов с более прямыми ответами, в том числе, возможно, «вы не можете сделать это никоим образом, ни как», если это действительно так.

Спасибо огромное!

EDIT, СПАСИБО ЗА ОТВЕТ НИЖЕ, вот что я закончил с ...

class semiImmutableList(list): 
    def __setitem__(self, *args): 
     raise TypeError("'semiImmutableList' object doesn't support item assignment") 
    __setslice__ = __setitem__ 
    def __delitem__(self, *args): 
     raise TypeError("'semiImmutableList' object doesn't support item deletion") 
    __delslice__ = __delitem__ 
    def append(self, *args): 
     raise AttributeError("'semiImmutableList' object has no attribute 'append'") 
    def extend(self, *args): 
     raise AttributeError("'semiImmutableList' object has no attribute 'extend'") 
    def insert(self, *args): 
     raise AttributeError("'semiImmutableList' object has no attribute 'insert'") 
    def remove(self, *args): 
     raise AttributeError("'semiImmutableList' object has no attribute 'remove'") 
    def pop(self, *args): 
     raise AttributeError("'semiImmutableList' object has no attribute 'pop'") 
    def __init__(self): 
     x = [1, 2, 3] 
     super(semiImmutableList, self).__init__(x) 
    def resetMyself(self): 
     super(semiImmutableList,self).append(5) 

Любые улучшения/корректировки выше, что вы можете увидеть, пожалуйста, напишите. Кажется, что дублирование AttributeError может быть объединено?

+0

Не уверен, что вы подразумеваете под «любым экземпляром неизменяемого объекта может быть восстановлен с разными значениями». Новые объекты с разными значениями могут быть созданы и привязаны к одному и тому же имени, но неизменяемый объект не может быть изменен (следовательно, этот термин). «Восстановленный» неизменяемый объект - это другой объект. – martineau 2010-11-29 18:44:35

+0

Да, плохая фразировка с моей стороны. Если x = (1, 2, 3), он никогда не может быть изменен, но x может стать другим объектом, включая другой кортеж с простым переназначением ... x = (3, 4, 5). x есть x, но первый связанный с ним объект tuple x просто исчез, не изменился. – sansjoe 2010-11-29 19:43:02

+0

def resetMyself (self): super (semiImmutableList, self) .append (5): зачем использовать super вместо передачи себя в список? Мне было интересно, был ли ваш пример неудачным, потому что вы не вернули себя, каким-то образом (у нас было объяснение о том, как это сделать, а не почему это не работает) – 2017-08-10 10:51:20

ответ

1

Довольно легко, все, что вам нужно сделать, это обернуть список.

class ImmutableList(object): 
    def __init__(self, *args): 
     self.__values = args; # internally we store the values in a list 

    # make imuList[0] = 2 raise an error, just like a tuple would 
    def __setitem__(self, index, value): 
     raise TypeError('ImmutableList does not support item assignment') 

    # del imuList[0] should also raise 
    def __delitem__(self, index, value): 
     raise TypeError('ImmutableList does not support item deletion')** 

    # make our imuList indexable, also catch the normal index error and raise one 
    # that tells that this is an immutable list, will make it easier to debug :) 
    def __getitem__(self, index): 
     try: 
      return self.__values[index] 

     except IndexError: 
      raise IndexError('ImmutableList index out of range') 

    # the usual stuff 
    def __repr__(self): 
     return repr(self.__values) 

    def __str__(self): 
     return str(self.__values) 

# create a new imulist 
e = ImmutableList(1, 2, 3, 4) 

# works! 
print e[0] 

# raises an error 
e[0] = 5 

# raises another error 
print e[9] 

Теперь все, что вам нужно сделать, это изменить self._values внутри класса. Один из последних советов, по-прежнему можно возиться с self._values снаружи, потому что Python не поддерживает private members.

Вы можете принять дополнительные меры против манипулирования __values путем подкласса из списка напрямую, но это больше работает, и все еще можно поиграть со значениями, используя list.__setitem__(imListInstance, 0, 5) и тому подобное.

2

Если вы хотите изменить тип кортежа, используйте список.

редактировать:

попробовать это

class FrankenList(object): 
    def __init__(self, init=None): 
     self.__data = init or [] 

    def __getitem__(self, key): 
     return self.__data[key] 

    def __repr__(self): 
     return repr(self.__data) 

    def __str__(self): 
     return str(self.__data)