Python子类化元组对象,能够在内部重新实例化自身
我明白Python中可变对象和不可变对象的概念,这没问题。虽然不可变对象的本质值不能直接修改,但我们可以用不同的值重新创建一个不可变对象的实例。我想做的是在一个元组的子类中建立一个内部函数,让它可以以一种受控的方式重新赋值。这个基本功能我找了很久都没找到,希望能得到一些帮助。
举个例子,我想做到这样的事情,但显然这样做是行不通的。
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)
我在这个网站上看了很多类似问题的回答,知道有些人可能会问“你为什么想这么做?”但我希望大家能直接给出答案,包括可能的“你根本不能这样做”,如果真是这样的话。
非常感谢大家!
补充一下,感谢下面的回答,这就是我最后得到的结果...
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的重复抛出可以合并吗?
2 个回答
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)
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并不支持真正的私有成员。
如果你想更好地防止别人修改 __values
,可以直接从列表继承,但这样会多花一些功夫。而且即使这样,别人还是可以通过 list.__setitem__(imListInstance, 0, 5)
之类的方法来改动值。