2017-05-16 1 views
4

부정적인 정지 예상대로 작동하지 않습니다 : STR .__ getslice__ 내가 파이썬 2.7에서 다음 코드를 실행하려고했다

foo = "python is awesome" 
print foo[10:16] 
print foo.__getslice__(10,16) 
print foo[10:-1] 
print foo.__getslice__(10,-1) 

이 마지막이 "awsome" 인쇄 모두 제외. 그러나 foo.__getslice__(10,-1)은 빈 문자열을 반환했습니다. 왜 그래야만하지?

+2

문자열에 특정되지 않습니다. 'foo = list (foo)'와 같은 동작을합니다. 또한'str'과'list' 모두'help (* .__ getslice __)'는 명시 적으로 음수 인덱스가 지원되지 않는다고 명시합니다. 'foo [slice (10, -1)]'는 잘 동작합니다. –

답변

4

문자열은 이렇게 대답은 당신이 많은 약 를 모르면 이해하기 위해 그 솔직하지 구현하지만, 어쨌든 최선을 다할된다

직접 __getslice__를 호출하는 경우 당신은 string_slice를 사용합니다 :

static PyObject * 
string_slice(PyStringObject *a, Py_ssize_t i, Py_ssize_t j) 
    /* j -- may be negative! */ 
{ 
    if (i < 0) 
     i = 0; 
    if (j < 0) 
     j = 0; /* Avoid signed/unsigned bug in next line */ 
    if (j > Py_SIZE(a)) 
     j = Py_SIZE(a); 
    if (i == 0 && j == Py_SIZE(a) && PyString_CheckExact(a)) { 
     /* It's the same as a */ 
     Py_INCREF(a); 
     return (PyObject *)a; 
    } 
    if (j < i) 
     j = i; 
    return PyString_FromStringAndSize(a->ob_sval + i, j-i); 
} 
여기

i는 시작 인덱스와 j는 정지 인덱스입니다. 정지가 0보다 작은 경우 0 (if (j < 0) j = 0;)으로 설정되고 시작보다 작기 때문에 시작 (if (j < i) j = i;)으로 설정됩니다. 따라서 start = 10으로 끝나고 stop = 10으로 끝납니다. 이것은 빈 문자열입니다.

하지만 []를 사용하는 경우는 (내가 그 방법의 관련 부분을 포함 단지 것) string_subscript 전화 할게 :

static PyObject* 
string_subscript(PyStringObject* self, PyObject* item) 
{ 
    /* ... */ 
    if (PySlice_Check(item)) { 
     Py_ssize_t start, stop, step, slicelength, cur, i; 
     /* ... */ 

     if (_PySlice_Unpack(item, &start, &stop, &step) < 0) { 
      return NULL; 
     } 
     slicelength = _PySlice_AdjustIndices(PyString_GET_SIZE(self), &start, 
              &stop, step); 

     /* ... */ 
     if (step == 1) { 
      return PyString_FromStringAndSize(
       PyString_AS_STRING(self) + start, 
       slicelength); 
     } 
     /* ... */ 
    } 
    /* ... */ 
} 

제대로_PySlice_AdjustIndices와 인덱스를 (이 PySlice_AdjustIndices처럼) 조정합니다. 즉, 함수 len(string) - 1의 정지 -1의 조리개를 변환한다 :

Py_ssize_t PySlice_AdjustIndices (Py_ssize_t 길이 Py_ssize_t * 시작 Py_ssize_t * 정지 Py_ssize_t 공정)

조정 시작/종료 슬라이스 인덱스 지정된 길이의시 v 스를 가정합니다. 범위를 벗어난 인덱스는 정상 슬라이스의 처리와 일관된 방식으로 잘립니다.

실제로 호출되는 함수는 해당 함수와 다를 수 있습니다. 그러나이 문서는 두 가지 모두에 적용됩니다.


그러나 일반적으로 __*__ 메서드는 직접 호출하면 안됩니다. 따라서 파이썬에서 버그인지 또는 의도 된 사용인지는 알 수 없습니다 (특정 종류의 슬라이스에 대해 내가 아는 모든 기능에 최적화 된 함수 일 수 있음).

그러나 __getslice__은 오래 전 사용되지 않았습니다.

+1

이것은 언어 이름이 태그 링크를 당혹스럽게한다는 사실에도 불구하고 훌륭한 대답입니다. :) –

관련 문제