¿Para qué es el tipo de búfer de Python?

136

Hay un buffertipo en python, pero no sé cómo puedo usarlo.

En el documento de Python, la descripción es:

buffer(object[, offset[, size]])

El argumento objeto debe ser un objeto que admita la interfaz de llamada del búfer (como cadenas, matrices y búferes). Se creará un nuevo objeto de búfer que hace referencia al argumento del objeto. El objeto de búfer será un segmento desde el principio del objeto (o desde el desplazamiento especificado). El segmento se extenderá hasta el final del objeto (o tendrá una longitud dada por el argumento de tamaño).

satoru
fuente

Respuestas:

145

Un ejemplo de uso:

>>> s = 'Hello world'
>>> t = buffer(s, 6, 5)
>>> t
<read-only buffer for 0x10064a4b0, size 5, offset 6 at 0x100634ab0>
>>> print t
world

El búfer en este caso es una subcadena, que comienza en la posición 6 con longitud 5, y no ocupa espacio de almacenamiento adicional: hace referencia a un segmento de la cadena.

Esto no es muy útil para cadenas cortas como esta, pero puede ser necesario cuando se usan grandes cantidades de datos. Este ejemplo usa un mutable bytearray:

>>> s = bytearray(1000000)   # a million zeroed bytes
>>> t = buffer(s, 1)         # slice cuts off the first byte
>>> s[1] = 5                 # set the second element in s
>>> t[0]                     # which is now also the first element in t!
'\x05'

Esto puede ser muy útil si desea tener más de una vista de los datos y no desea (o no puede) tener varias copias en la memoria.

Tenga en cuenta que bufferha sido reemplazado por el mejor nombrado memoryviewen Python 3, aunque puede usarlo en Python 2.7.

Tenga en cuenta también que no puede implementar una interfaz de búfer para sus propios objetos sin profundizar en la API de C, es decir, no puede hacerlo en Python puro.

Scott Griffiths
fuente
Gracias por tu explicación. Pero todavía no entiendo cuál es la diferencia entre el almacenamiento en búfer y el corte simple. El uso s[6:11]tampoco requiere espacio de almacenamiento adicional, ¿estoy equivocado?
satoru
9
En general, un segmento tendrá almacenamiento adicional, por lo que sí s[6:11]será una copia. Si configura t = s[6:11]y luego del s, libera la memoria que fue tomada s, demostrando que tfue copiada. (Para ver esto, necesita una smemoria más grande y rastrear el uso de Python). Sin embargo, es mucho más eficiente hacer la copia si no hay muchos datos involucrados.
Scott Griffiths
1
Muchas gracias :) Por cierto, ¿podría decirme qué herramienta puedo usar para rastrear el uso de memoria de Python?
satoru el
Para el uso de memoria, consulte stackoverflow.com/questions/110259 por ejemplo. A veces es más fácil ver el uso de Python en el Administrador de tareas / Monitor de actividad / arriba.
Scott Griffiths
13
Para los novatos de Python como yo: el buffer es memoryview en Python 3
Dirk Bester
25

Creo que los buffers son, por ejemplo, útiles cuando se conecta Python a bibliotecas nativas. (Guido van Rossum explica bufferen esta publicación de la lista de correo ).

Por ejemplo, numpy parece usar el búfer para un almacenamiento de datos eficiente:

import numpy
a = numpy.ndarray(1000000)

el a.dataes un:

<read-write buffer for 0x1d7b410, size 8000000, offset 0 at 0x1e353b0>
Andre Holzner
fuente