2014-09-01 12 views
5
>>> class Potato(object): 
... def __getslice__(self, start, stop): 
...  print start, stop 
...   
>>> sys.maxint 
9223372036854775807 
>>> x = sys.maxint + 69 
>>> print x 
9223372036854775876 
>>> Potato()[123:x] 
123 9223372036854775807 

Perché la chiamata a getslice non rispetta lo stop Ho inviato, sostituendo invece in modo silenzioso 2^63 - 1? Significa che l'implementazione di __getslice__ per la tua sintassi di solito non è sicura con i long?Punti d'estremità invisibili troncati

Posso fare tutto quello che mi serve con __getitem__ in ogni caso, mi chiedo solo perché __getslice__ è apparentemente rotto.

Modifica: Dov'è il codice in CPython che tronca la sezione? Questa parte di python (language) spec o solo una "feature" di cpython (implementazione)?

+0

deve essere detto: "perché sì, vorrei 2^64 fette di questa bella patata". Seriamente però, vorrei davvero avere una risposta – inspectorG4dget

+1

È una fetta .. e succederebbe lo stesso con una porzione più piccola come 'maxint-2: maxint + 2' :) – wim

risposta

6

Il codice Python C che gestisce affettare per oggetti che implementano l'sq_slice fessura, non in grado di gestire eventuali interi sopra Py_ssize_t (== sys.maxsize). Lo slot sq_slice corrisponde all'equivalente C-API del metodo speciale __getslice__.

Per una sezione a due elementi, Python 2 utilizza uno degli SLICE+* opcodes; questo viene quindi gestito dallo apply_slice() function. Questo utilizza _PyEval_SliceIndex function per convertire gli oggetti indice Python (int, long o qualsiasi cosa che implementa lo __index__ method) in un numero intero Py_ssize_t. Il metodo ha il seguente commento:

/* Extract a slice index from a PyInt or PyLong or an object with the 
    nb_index slot defined, and store in *pi. 
    Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX, 
    and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1. 
    Return 0 on error, 1 on success. 
*/ 

Ciò significa che qualsiasi affettatura in Python 2 utilizzando la sintassi 2-valore è limitato a valori nell'intervallo sys.maxsize quando viene fornita una fessura sq_slice.

affettare utilizzando il modulo tre valori (item[start:stop:stride]) utilizza il BUILD_SLICE opcode invece (seguita da BINARY_SUBSCR) e questo crea invece una slice() object senza limitare a sys.maxsize.

Se l'oggetto non implementa una fessura sq_slice() (quindi non __getslice__ presente) la funzione apply_slice() rientra anche tornare a utilizzare un oggetto slice().

Per quanto riguarda questo è un dettaglio di implementazione o parte della lingua: lo Slicings expression documentation distingue tra simple_slicing e extended_slicing; il primo consente solo il modulo short_slice. Per semplice tranciatura gli indici devono essere interi semplici:

Le espressioni di partenza e superiore, se presente, deve esprimere un intero; i valori predefiniti sono zero e lo sys.maxint, rispettivamente.

Questo suggerisce che Python 2 lingua limita gli indici a sys.maxint valori, non consentendo interi lunghi. In Python 3 il taglio semplice è stato completamente eliminato dalla lingua.

Se il codice deve sostenere affettare con valori al di là sys.maxsizee si deve ereditare da un tipo che implementa __getslice__ quindi le opzioni sono:

  • utilizzare la sintassi di tre valori, con None per il passo:

    Potato()[123:x:None] 
    
  • per creare slice() oggetti esplicitamente:

slice() oggetti in grado di gestire interi long bene; tuttavia la slice.indices() method non può gestire lunghezze sopra sys.maxsize ancora:

>>> import sys 
>>> s = slice(0, sys.maxsize + 1) 
>>> s 
slice(0, 9223372036854775808L, None) 
>>> s.stop 
9223372036854775808L 
>>> s.indices(sys.maxsize + 2) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
OverflowError: cannot fit 'long' into an index-sized integer 
+0

Grazie. Puoi commentare se questo è linguaggio o implementazione? – wim

+0

@wim: la linea è sfocata qui; Direi che questo è un limite di implementazione. –

+2

@wim: aggiornato per citare la documentazione su questo; sembra essere un problema linguistico qui, non un dettaglio di implementazione. –

Problemi correlati