我正在尝试从Python 3中的切片中获取原始列表以进行调试,例如
L = [1,2,3,4,5]
S = L[2:3]
X = S.originalList()
# X == L
在python中甚至可以吗?
答案 0 :(得分:1)
不可能使用标准python list
,因为切片会创建一个新列表。列表中引用的项指向相同的对象(它是一个浅层副本),但这没有用,因为python列表只是一个指针列表的包装器(有很多额外的东西)。
这样可以更改一个列表的列表元素而不修改另一个列表,这使得评估.originallist
属性或方法应该检查的情况非常复杂。
>>> list1 = [1,2,3,4,5,6]
>>> list2 = list1[2:5]
>>> list2[1] = 10
>>> list1, list2
([1, 2, 3, 4, 5, 6], [3, 10, 5])
但是,已经有一个数据结构在切片时使用内存视图而不是浅层副本:numpy.ndarray
和它的属性numpy.ndarray.base
。
>>> import numpy as np
>>> arr1 = np.array([1,2,3,4,5,6])
>>> arr2 = arr1[2:5]
>>> arr2.base is arr1 # it's called "base" instead of "originallist".
True
请注意,对于numpy数组,对arr2
的任何更改都会传播到arr1
!根据你的用例,numpy.arrays可能有点过分,只需一个简单的子类或包装列表即可。
答案 1 :(得分:0)
您可以为需要此类功能的列表创建扩展类。首先,您需要一个可以添加属性的列表(通过http://code.activestate.com/recipes/579103-python-addset-attributes-to-list/):
class L(list):
def __new__(self, *args, **kwargs):
return super(L, self).__new__(self, args, kwargs)
def __init__(self, *args, **kwargs):
if len(args) == 1 and hasattr(args[0], '__iter__'):
list.__init__(self, args[0])
else:
list.__init__(self, args)
self.__dict__.update(kwargs)
def __call__(self, **kwargs):
self.__dict__.update(kwargs)
return self
现在您可以向此类添加另一种方法:
def slice(self, left, right):
S = L(self[left:right])
S.originalList = self
return S
现在你可以这样做:
l = L(1,2,3,4,5)
S = l.slice(2,3)
try:
X = S.originalList
except AttributeError:
pass # here you can handle the case where S doesn't have an original list
# X == L