2017-01-09 4 views
2

私はスライスが含まれているリストを取得できますか?

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

のようなもの、デバッグ目的のためのPython 3のスライスから元のリストを取得しようとしていますが、Pythonであっても可能ですか?

+9

いいえ、不可能です。スライシングはリストの* copy *を作成し、オリジナルへの接続を保持しません。 –

+0

ハードコピーのようなスライスですか?もしそうでなければ、どこかに連想性があるかもしれないからです。 –

+2

@ Ev.Kounis *「難しい」*コピーは何を意味しますか?彼らは*浅い*コピーです。 – jonrsharpe

答えて

1

標準のPython listでは、スライスによって新しいリストが作成されるため、不可能です。リスト内で参照されている項目は、同じオブジェクト(浅いコピー)を指していますが、Pythonリストはポインターのリストのためのラッパー(多くの追加機能を持つ)なので役に立ちません。

これは、一方のリストのリスト要素を変更することなくリストの要素を変更することができるため、.originallistのプロパティまたはメソッドがチェックする必要があるかを評価するのが極端に複雑になります。 numpy.ndarrayをし、それが属性numpy.ndarray.baseです:

>>> 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]) 

は、しかし、すでにスライスされたとき、代わりに浅いコピーのメモリー・ビューを使用するデータ構造があります。

>>> 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は過剰なものになる可能性があり、リストの周りの単純なサブクラスまたはラッパーで十分です。

0

この種の機能が必要なリストの拡張クラスを作成することができます。だから、最初のあなたは(http://code.activestate.com/recipes/579103-python-addset-attributes-to-list/経由)の属性を追加できるリストが必要になります:

def slice(self, left, right): 
     S = L(self[left:right]) 
     S.originalList = self 
     return S 

そして今、あなたが行うことができます:

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 

今、あなたは、このクラスに別のメソッドを追加することができます

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 
関連する問題