Я ищу эквивалент Python для Python C-API PyObject_CheckBuffer.
т.е. Я хотел бы проверить, поддерживает ли объект буферный протокол, но из Python.
Я ищу эквивалент Python для Python C-API PyObject_CheckBuffer.
т.е. Я хотел бы проверить, поддерживает ли объект буферный протокол, но из Python.
Я думаю, вы просто должны использовать стандартный метод try-it-and-see-if-it-works:
# New-style buffer API, for Python 2.7 and 3.x.
# PyObject_CheckBuffer uses the new-style API.
# 2.6 also has the new-style API, but no memoryview,
# so you can't use it or check compatibility from Python code.
try:
memoryview(thing)
except TypeError:
# Doesn't support it!
# Old-style API. Doesn't exist in 3.x.
# Not quite equivalent to PyObject_CheckBuffer.
try:
buffer(thing)
except TypeError:
# Doesn't support it!
Работая с короткими фрагментами данных в критически важном для кода коде, мне пришлось попробовать разные подходы. В зависимости от вашего приложения, один может быть лучше, чем другие.
def ensure_bytes__try(data):
try:
# memoryview used only for testing type; 'with' releases the view instantly
with memoryview(data):
return data
except TypeError:
return data.encode()
def ensure_bytes__isinstance(data):
# Explicitly test for some bytes-like types
# - misses array.array, numpy.array and all other types not listed here
return data if isinstance(data, (bytes, bytearray, memoryview)) else data.encode()
def ensure_bytes__hasattr(data):
# Works as long as your bytes-like does not have 'encode'
return data.encode() if hasattr(data, "encode") else data
def ensure_bytes__args(data=None, data_bytes=None):
# Avoid autodetection by using explicit arguments
return data_bytes if data is None else data.encode()
Следующий тест показывает время, используемое каждой реализацией в Python 3.7.4:
ensure_bytes__try(b"foo") ▒▒▒▒█████████████████ 438 ns
ensure_bytes__try("foo") ▒▒▒▒▒██████████████████████████████████ 797 ns
ensure_bytes__isinstance(b"foo") ▒▒▒▒█████████ 277 ns
ensure_bytes__isinstance("foo") ▒▒▒▒▒███████████████████ 489 ns
ensure_bytes__hasattr(b"foo") ▒▒▒▒████ 171 ns
ensure_bytes__hasattr("foo") ▒▒▒▒▒█████████ 287 ns
ensure_bytes__args(data_bytes=b"foo") ▒▒▒▒██ 121 ns
ensure_bytes__args(data="foo") ▒▒▒▒▒█████ 216 ns
Более короткая полоса означает быстрее. Заштрихованная светлая часть каждого столбца представляет собой эталонное время, измеренное для ref_bytes(b"foo")
(84 & # 8239; нс) и ref_str("foo")
(100 & # 8239; нс):
def ref_bytes(data): return data
def ref_str(data): return data.encode()