29

Python 3.3 を使用しています。sliceオブジェクトを取得し、それを使用して新しいオブジェクトを作成したいと考えていrangeます。

次のようになります。

>>> class A:
    def __getitem__(self, item):
        if isinstance(item, slice):
            return list(range(item.start, item.stop, item.step))

>>> a = A()
>>> a[1:5:2] # works fine
[1, 3]
>>> a[1:5] # won't work :(
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    a[1:5] # won't work :(
  File "<pyshell#9>", line 4, in __getitem__
    return list(range(item.start, item.stop, item.step))
TypeError: 'NoneType' object cannot be interpreted as an integer

さて、問題はここで明らかです -値としてrange受け入れませんNone:

>>> range(1, 5, None)
Traceback (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    range(1, 5, None)
TypeError: 'NoneType' object cannot be interpreted as an integer

しかし、(私にとって)明白ではないのは解決策です。どのような場合でも機能するように呼び出すにはどうすればよいrangeですか? 私はそれを行うための素敵なpythonicの方法を探しています。

4

7 に答える 7

16

試す

class A:
    def __getitem__(self, item):
        ifnone = lambda a, b: b if a is None else a
        if isinstance(item, slice):
            if item.stop is None:
                # do something with itertools.count()
            else:
                return list(range(ifnone(item.start, 0), item.stop, ifnone(item.step, 1)))
        else:
            return item

これは再解釈さ.startれ、.step適切に再解釈されますNone


別のオプションは.indices()、スライスの方法です。エントリの数で呼び出されNone、適切な値に再解釈され、指定された長さパラメーターの周りに負の値がラップされます。

>>> a=slice(None, None, None)
>>> a.indices(1)
(0, 1, 1)
>>> a.indices(10)
(0, 10, 1)
>>> a=slice(None, -5, None)
>>> a.indices(100)
(0, 95, 1)

それは、負のインデックスで何をするつもりかによって異なります...

于 2012-12-13T07:54:36.117 に答える
1

item.step is None私はブランチを特別なケースにします:

def __getitem__(self, item):
    if isinstance(item, slice):
        if item.step is None:
            return list(range(item.start, item.stop))
        return list(range(item.start, item.stop, item.step))

正しくカウントダウンする必要がある範囲を処理します。

于 2012-12-13T08:13:24.803 に答える
0

最後の例a[1:5]では、item.step == Noneやろうとしていますがrange(1, 5, None)、もちろんエラーが発生します。迅速な修正方法:

class A:
    def __getitem__(self, item):
        if isinstance(item, slice):
            return list(range(item.start, item.stop, item.step if item.step else 1)) #Changed line!

しかし、それはあなたの問題を示すだけです。これは最善の方法ではありません。

于 2012-12-13T08:00:17.857 に答える