我从一个据称严肃的来源下载了一个sage脚本。它在我的计算机上不起作用,并且快速调试表明问题来自这样的事实:在某些时候,作者正在做的事情就好像n元素列表从1到n编号(而“正常”编号)在Python中(因此)sage是0..n-1)。
我错过了什么?是否有一个隐藏在某处的全局变量会改变这种约定,比如在APL中?
感谢您的帮助(我希望我的问题很清楚,尽管我对英语和CSish都很难掌握......)
答案 0 :(得分:6)
Python(以及sage)列表总是从0开始编号,并且没有办法改变它。
在第449行的http://hg.python.org/cpython/file/70274d53c1dd/Objects/listobject.c中查看CPython的来源:
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 arrays are always zero-based。所以Python列表也总是从零开始。
答案 1 :(得分:3)
为您移动索引的简单类为可重用的东西提供了一个干净的界面。
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]
答案 2 :(得分:0)
我也面临着如何实现索引方法从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中添加了一个'Dummy',完成了算法中的所有工作并再次移除了'dummy'。这只是一种作弊方法。
答案 3 :(得分:0)
我建议子类化,例如collections.abc.MutableSequence之类的东西,因为一旦协议(在这种情况下为__getitem__
,__setitem__
,__delitem__
,__len__
,insert
)已实现的 all 列表方法应适用于自定义序列类型。
我想出的解决方案使用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}"
例如流行音乐现在可以使用,尽管它没有明确实现:
ol = OneList([1,2,3,4])
print(ol.pop(1))
ol.pop(0) # IndexError
尽管如此,这感觉有些混乱,如果有人共享更好的解决方案,我将不胜感激。
l = [] l.extend([]) 打印(l)
答案 4 :(得分:-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']