76

組み込み関数の用途とは何sliceですか?どうすれば使用できますか?
私が知っているPythonicスライシングの直接的な方法- l1[start:stop:step]。スライスオブジェクトがあるかどうか知りたいのですが、どうすれば使用できますか?

4

6 に答える 6

104

[start:end:step]表記を行う場合と同じフィールドでsliceを呼び出すことにより、スライスを作成します。

sl = slice(0,4)

スライスを使用するには、それがインデックスであるかのようにリストまたは文字列に渡します。

>>> s = "ABCDEFGHIJKL"
>>> sl = slice(0,4)
>>> print(s[sl])
'ABCD'

固定長のテキストフィールドのファイルがあるとします。スライスのリストを定義して、このファイルの各「レコード」から値を簡単に抽出できます。

data = """\
0010GEORGE JETSON    12345 SPACESHIP ST   HOUSTON       TX
0020WILE E COYOTE    312 ACME BLVD        TUCSON        AZ
0030FRED FLINTSTONE  246 GRANITE LANE     BEDROCK       CA
0040JONNY QUEST      31416 SCIENCE AVE    PALO ALTO     CA""".splitlines()


fieldslices = [slice(*fielddef) for fielddef in [
    (0,4), (4, 21), (21,42), (42,56), (56,58),
    ]]
fields = "id name address city state".split()

for rec in data:
    for field,sl in zip(fields, fieldslices):
        print("{} : {}".format(field, rec[sl]))
    print('')

# or this same code using itemgetter, to make a function that
# extracts all slices from a string into a tuple of values
import operator
rec_reader = operator.itemgetter(*fieldslices)
for rec in data:
    for field, field_value in zip(fields, rec_reader(rec)):
        print("{} : {}".format(field, field_value))
    print('')

プリント:

id : 0010
name : GEORGE JETSON    
address : 12345 SPACESHIP ST   
city : HOUSTON       
state : TX

id : 0020
name : WILE E COYOTE    
address : 312 ACME BLVD        
city : TUCSON        
state : AZ

id : 0030
name : FRED FLINTSTONE  
address : 246 GRANITE LANE     
city : BEDROCK       
state : CA

id : 0040
name : JONNY QUEST      
address : 31416 SCIENCE AVE    
city : PALO ALTO     
state : CA
于 2010-10-12T04:43:17.733 に答える
38

シーケンスに続く角かっこは、かっこ内の内容に応じて、インデックス付けまたはスライスのいずれかを示します。

>>> "Python rocks"[1]    # index
'y'
>>> "Python rocks"[1:10:2]    # slice
'yhnrc'

これらのケースは両方とも__getitem__()、シーケンスのメソッドによって処理されます(または__setitem__()、等号の左側にある場合)。インデックスまたはスライスは単一の引数としてメソッドに渡されます。Pythonがこれを行う方法は、スライス表記を変換することです。 、(1:10:2、この場合)をスライスオブジェクトに:slice(1,10,2)

したがって、独自のシーケンスのようなクラスを定義する場合、または別のクラスの__getitem__または__setitem__または__delitem__メソッドをオーバーライドする場合は、インデックス引数をテストして、それがまたはであるintかどうかを判断し、それsliceに応じて処理する必要があります。

def __getitem__(self, index):
    if isinstance(index, int):
        ...    # process index as an integer
    elif isinstance(index, slice):
        start, stop, step = index.indices(len(self))    # index is a slice
        ...    # process slice
    else:
        raise TypeError("index must be int or slice")

オブジェクトには、、、およびの3つの属性と、sliceオブジェクトstartの長さである単一の引数を取り、3つのタプルを返す1つのメソッド:があります。stopstepindices(start, stop, step)

于 2010-10-12T06:16:45.603 に答える
8
>>> class sl:
...  def __getitem__(self, *keys): print keys
...     
>>> s = sl()
>>> s[1:3:5]
(slice(1, 3, 5),)
>>> s[1:2:3, 1, 4:5]
((slice(1, 2, 3), 1, slice(4, 5, None)),)
>>>
于 2010-10-12T06:20:48.513 に答える
3

このslice関数はスライスオブジェクトを返します。スライスオブジェクトはPythonの内部型の1つであり、読み取りパフォーマンス用に最適化されています。それらの属性はすべて読み取り専用です。

デフォルトの動作を変更したい場合は、変更sliceが役立つ場合があります。たとえば、lxmlスライス表記を使用してDOM要素にアクセスします(ただし、自分でどのように行ったかは確認していません)。

于 2010-10-12T03:49:06.660 に答える
1

変数に基づいて文字列をサブセット化することに答えようとしているときに、numpyにはスライスオブジェクトを定義する構文的に優れた方法があることを思い出しました。

>>> import numpy as np
>>> s = "The long-string instrument is a musical instrument in which the string is of such a length that the fundamental transverse wave is below what a person can hear as a tone."
>>> z = np.s_[18:26]  # in this case same as slice(18, 26, None)
>>> s[z]
'strument'

ここで解決される問題は、後で使用するためにスライスを変数に格納する方法であり、それnp.s_を実行できるようにします。はい、組み込みではありませんが、元の質問がここにリダイレクトされたので、私の答えもここに属しているように感じます。また、numpyは、Python、IIRCに非常に高度なスライス機能が追加された理由の1つでした。

より複雑な「スライス」の例:

>>> data = np.array(range(6)).reshape((2, 3))
>>> z = np.s_[:1, 1:2]
>>> data[z]
array([[1]])
>>> data
array([[0, 1, 2],
       [3, 4, 5]])
>>> z
(slice(None, 1, None), slice(1, 2, None))

ここで、zはスライスのタプルになります。

于 2019-08-18T16:32:18.367 に答える
0

スライスオブジェクトを使用すると、プログラムでスライスを生成および操作できます。特に多次元のnumpy配列の場合、特に事前に次元がわからない場合は、必要な軸または次元を指定するためにオンザフライでスライスを作成することをお勧めします。

import numpy as np
dimension = np.random.randint(10) # Might have up to 10 dimensions
shape = []
for d in range(dimension):
    shape.append(np.random.randint(10))
zz = np.random.rand(tuple(shape))
print(zz)
>>> array([[0.68379351, 0.50854469, 0.64578775, 0.73441699, 0.28977396],
           [0.88797164, 0.81603025, 0.63978659, 0.22677299, 0.93455738],
           [0.0892855 , 0.28048706, 0.04262895, 0.9353467 , 0.13062249],
           [0.88561035, 0.93378367, 0.12124208, 0.25600301, 0.96035638]])

ここで、データは2次元(4行5列)になりましたが、その保証はありませんでした。どのようにスライスをリクエストしzzますか?

1つの問題は、Pythonのスライス表記を操作できないことです。スライス操作以外では有効な構文ではありません。

my_slice = 2:3:1
>>> SyntaxError: Invalid Syntax

文字列を作成する方法で、ループ内で必要な正確なスライスリクエストを作成できたらどうなりますか?それは素晴らしいことではないでしょうか?つまり、文字列を使用してそれを実行できることは確かですが、面倒であり、が必要になりますeval

your_slice_definitions = [(2,3,1), *[(None, None, None)]*(zz.ndim - 1)] 
my_slice_str = ""
for slice_start, slice_end, slice_step in your_slice_definitions:
    my_slice_str += "{}:{}:{},".format(slice_start, slice_end, slice_step)
eval("zz["+my_slice_str+"])

これがここにあります:sliceオブジェクトはこれを可能にします。リストとそれらのタプルをオンザフライでアセンブルしたり、関数パラメーターとして渡したり、並べ替えたり、シャッフルしたりすることができます。

my_slices = []
for slice_start, slice_end, slice_step in your_slice_definitions:
    my_slices += slice(slice_start, slice_end, slice_step)
print(zz[my_slices])
>>> array([[0.0892855 , 0.28048706, 0.04262895, 0.9353467 , 0.13062249]])
于 2020-07-15T23:46:02.253 に答える