L = [1,2,3,4,5]
S = L[2:3]
X = S.originalList()
# X == L
のようなもの、デバッグ目的のためのPython 3のスライスから元のリストを取得しようとしていますが、Pythonであっても可能ですか?
L = [1,2,3,4,5]
S = L[2:3]
X = S.originalList()
# X == L
のようなもの、デバッグ目的のためのPython 3のスライスから元のリストを取得しようとしていますが、Pythonであっても可能ですか?
標準の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は過剰なものになる可能性があり、リストの周りの単純なサブクラスまたはラッパーで十分です。
この種の機能が必要なリストの拡張クラスを作成することができます。だから、最初のあなたは(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
いいえ、不可能です。スライシングはリストの* copy *を作成し、オリジナルへの接続を保持しません。 –
ハードコピーのようなスライスですか?もしそうでなければ、どこかに連想性があるかもしれないからです。 –
@ Ev.Kounis *「難しい」*コピーは何を意味しますか?彼らは*浅い*コピーです。 – jonrsharpe