11

我从一个所谓的严肃来源下载了一个圣人脚本。它在我的计算机上不起作用,并且快速调试表明问题来自于这样一个事实,即在某些时候,作者正在做一个 n 元素列表从 1 到 n 编号(而“正常”编号在 Python 中,(因此)sage 是 0..n-1)。

我错过了什么?是否有隐藏在某个地方的全局变量会改变这个约定,比如在 APL 中?

感谢您的帮助(尽管我对英语和 CSish 的掌握很弱,但我希望我的问题很清楚......)

4

5 回答 5

8

Python(因此是 sage)列表总是从 0 开始编号,并且没有办法改变它。

查看 CPython 的源代码,位于http://hg.python.org/cpython/file/70274d53c1dd/Objects/listobject.c的第 449 行:

static PyObject *
list_item(PyListObject *a, Py_ssize_t i)
{
    if (i < 0 || i >= Py_SIZE(a)) {
        if (indexerr == NULL) {
            indexerr = PyString_FromString(
                "list index out of range");
            if (indexerr == NULL)
                return NULL;
        }
        PyErr_SetObject(PyExc_IndexError, indexerr);
        return NULL;
    }
    Py_INCREF(a->ob_item[i]);
    return a->ob_item[i];
}

项目查找直接委托给底层 C 数组,并且C 数组始终是从零开始的。所以 Python 列表也总是从零开始的。

于 2012-04-30T04:30:06.443 回答
5

一个为您移动索引的简单类为可重用的东西提供了一个干净的接口。

class Array(object):

    def __init__(self, items: list) -> None:
        self.items = items

    def __repr__(self) -> str:
        return '{}({})'.format(self.__class__.__name__, self.items)

    def __len__(self) -> int:
        return len(self.items)

    def __contains__(self, item: any) -> bool:
        return item in self.items

    def __getitem__(self, key: int) -> any:
        return self.items[key - 1]

    def __setitem__(self, key: int, value: any) -> None:
        self.items[key - 1] = value

    def __delitem__(self, key: int) -> None:
        del self.items[key - 1]
于 2018-02-19T20:03:36.353 回答
2

好吧,我也面临着同样的想法,关于如何实现从 1 开始的索引方法。我想实现插入排序算法,如下所示: 插入排序算法

正如我们已经知道 python 列表从 0 开始,我所做的如下:

A = ['dummy',5,2,6,4,1,3]
for j in range(2,len(A)):
    key = A[j]
    i=j-1
    while i>0 and A[i]>key:
        A[i+1] = A[i]
        i = i-1
    A[i+1] = key
A.pop(0)
print A

我刚刚在索引 0 中添加了一个“虚拟”,完成了算法中的所有工作,并再次删除了“虚拟”。这只是一种作弊方法。

于 2014-02-21T04:48:34.707 回答
0

我建议将子类化,例如collections.abc.MutableSequence,因为一旦实现了协议(在这种情况下:__getitem__, __setitem__, __delitem__, __len__, insert),所有列表方法都应该在自定义序列类型上工作。

我想出的解决方案使用 collections.abc.MutableSequence 和一个列表包装器 (_lst) 和一个辅助类组件,除了它是可下标的,它对任何事情都不了解,即它实现__getitem__了处理索引修改的方法。

import collections.abc

class _IndexComponent:
    def __getitem__(self, index):
        if index == 0: raise IndexError("Index 0 is a lie.")
        if index > 0: return index -1
        else: return index
        
class OneList(collections.abc.MutableSequence):

    def __init__(self, init: list = None) -> None:
        self._index_comp = _IndexComponent()
        self._lst = []
        if not init is None: # and isinstance(init, list)?
            self._lst.extend(init)
    
    def __getitem__(self, index: int) -> any:
        return self._lst[self._index_comp[index]]

    def __setitem__(self, index: int, val: any) -> None:
        self._lst[self._index_comp] = val

    def __delitem__(self, index: int) -> None:
        del self._lst[self._index_comp[index]]

    def __len__(self) -> int:
        return len(self._lst)

    def insert(self, index: int, val: any) -> None:
        self._lst.insert(self._index_comp[index], val)

    def __repr__(self) -> str:
        return f"{self._lst}"

现在例如 pop 工作,虽然它没有明确实现:

ol = OneList([1,2,3,4])
print(ol.pop(1))
ol.pop(0) # IndexError

不知何故,这感觉有点混乱,如果有人分享更好的解决方案,我会很高兴。

l = [] l.extend([]) 打印(l)

于 2020-11-20T19:03:01.397 回答
-1
In [1]: index_0 = ['foo', 'bar', 'quux']

In [2]: index_1 = [None] + index_0

In [3]: index_1[1]
Out[3]: 'foo'

In [4]: index_1[1:]
Out[4]: ['foo', 'bar', 'quux']
于 2020-10-22T02:08:17.450 回答