我可以获得切片所属的列表吗?

时间:2017-01-09 16:54:47

标签: python python-3.x

我正在尝试从Python 3中的切片中获取原始列表以进行调试,例如

L = [1,2,3,4,5]
S = L[2:3]
X = S.originalList()
# X == L

在python中甚至可以吗?

2 个答案:

答案 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