Найти в Дзене
@coolcoders

Встроенные типы данных Python часть 3

Оглавление

Просмотры памяти

memoryview объекты позволяют коду Python получать доступ к внутренним данным объекта, который поддерживает протокол буфера, без копирования.

класс memoryview( obj )

Создает объект memoryview, который ссылается на objobj должен поддерживать протокол буфера. Встроенные объекты, поддерживающие протокол буфера, включают bytes и bytearray.

A memoryview имеет понятие элемента, который является атомарной единицей памяти, обрабатываемой исходным объектом obj. Для многих простых типов, таких как bytes и bytearray, элемент является однобайтным, но другие типы, например, array.array могут иметь элементы большего размера.

len(view) равна длине tolist. Если view.ndim = 0, длина равна 1. Если view.ndim = 1, то длина равна количеству элементов в представлении. Для более высоких измерений длина равна длине представления в виде вложенного списка. Атрибут itemsize даст вам количество байт в одном элементе.

A memoryviewподдерживает нарезку и индексацию для предоставления своих данных. Одномерная нарезка приведет к подвиду:

>>> v = memoryview(b'abcefg')
>>> v[1]
98
>>> v[-1]
103
>>> v[1:4]
<memory at 0x7f3ddc9f4350>
>>> bytes(v[1:4])
b'bce'

Если format это один из спецификаторов собственного формата из structмодуля, индексирование с целым числом или кортежем целых чисел также поддерживается и возвращает один элемент с правильным типом. Одномерные представления памяти могут быть проиндексированы целым или одноцелочисленным кортежем. Многомерные просмотры памяти могут быть проиндексированы кортежами ровно ndim целых чисел, где ndim - количество измерений. Нульмерные просмотры памяти можно индексировать с помощью пустого кортежа.

Вот пример с небайтовым форматом:

>>> import array
>>> a = array.array('l', [-11111111, 22222222, -33333333, 44444444])
>>> m = memoryview(a)
>>> m[0]
-11111111
>>> m[-1]
44444444
>>> m[::2].tolist()
[-11111111, -33333333]

Если базовый объект доступен для записи, то memoryview поддерживает одномерное назначение срезов. Изменение размера не допускается:

>>> data = bytearray(b'abcefg')
>>> v = memoryview(data)
>>> v.readonly
False
>>> v[0] = ord(b'z')
>>> data
bytearray(b'zbcefg')
>>> v[1:4] = b'123'
>>> data
bytearray(b'z123fg')
>>> v[2:3] = b'spam'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: memoryview assignment: lvalue and rvalue have different structures
>>> v[2:6] = b'spam'
>>> data
bytearray(b'z1spam')

Одномерные представления памяти хешируемых (только для чтения) типов с форматами 'B', 'b' или 'c' также хешируются. Хеш определяется как  hash(m) == hash(m.tobytes()):

>>> v = memoryview(b'abcefg')
>>> hash(v) == hash(b'abcefg')
True
>>> hash(v[2:4]) == hash(b'ce')
True
>>> hash(v[::-2]) == hash(b'abcefg'[::-2])
True

Также можно нарезать одномерные представления памяти. Одномерные представления памяти с форматами 'B', 'b' или 'c' теперь хешируются.

memoryview может регистрироваться автоматически с помощью collections.abc.Sequence

Просмотры памяти можно индексировать с помощью кортежа целых чисел.

у memoryview есть несколько методов:

__eq__( exporter )

Воспоминания и Экспортер PEP 3118 равен, если их формы эквивалентны и если все соответствующие значения равны, когда соответствующие коды формата операндов интерпретируются с использованиемstructсинтаксиса.

Для подмножества structстрок формата, поддерживаемых в настоящее время tolist(), v и w равны, если : v.tolist() == w.tolist()

>>> import array
>>> a = array.array('I', [1, 2, 3, 4, 5])
>>> b = array.array('d', [1.0, 2.0, 3.0, 4.0, 5.0])
>>> c = array.array('b', [5, 3, 1])
>>> x = memoryview(a)
>>> y = memoryview(b)
>>> x == a == y == b
True
>>> x.tolist() == a.tolist() == y.tolist() == b.tolist()
True
>>> z = y[::-2]
>>> z == c
True
>>> z.tolist() == c.tolist()
True

Если какая-либо строка формата не поддерживается struct модулем, то объекты всегда будут сравниваться как неравные (даже если строки формата и содержимое буфера идентичны):

>>> from ctypes import BigEndianStructure, c_long
>>> class BEPoint(BigEndianStructure):
... _fields_ = [("x", c_long), ("y", c_long)]
...
>>> point = BEPoint(100, 200)
>>> a = memoryview(point)
>>> b = memoryview(point)
>>> a == point
False
>>> a == b
False

Обратите внимание, что, как и в случае с числами с плавающей запятой, v is w не подразумевает v == w для объектов memoryview.

tobytes( order=None )

Возвращает данные в буфере как байтовую строку. Это эквивалентно вызову bytes конструктора в memoryview.

>>> m = memoryview(b"abc")
>>> m.tobytes()
b'abc'
>>> bytes(m)
b'abc'

Для несмежных массивов результат равен представлению плоского списка со всеми элементами, преобразованными в байты. tobytes() поддерживает все строки формата, включая те, которые не входят в struct синтаксис модуля.

Порядок может быть {'C', 'F', 'A'}. Когда порядок равен 'C' или 'F', данные исходного массива преобразуются в порядок C или Fortran. Для непрерывных представлений "A" возвращает точную копию физической памяти. В частности, сохраняется порядок Fortran в памяти. Для несмежных представлений данные сначала преобразуются в C. order = None совпадает с order = 'C' .

hex( [ sep [ , bytes_per_sep ] ] )

Возвращает строковый объект, содержащий две шестнадцатеричные цифры для каждого байта в буфере.

>>> m = memoryview(b"abc")
>>> m.hex()
'616263'

Аналогично bytes.hex(), memoryview.hex()теперь поддерживаются необязательные параметры sep и bytes_per_sep для вставки разделителей между байтами в шестнадцатеричном выводе.

tolist( )

Возвращает данные в буфере в виде списка элементов.

>>> memoryview(b'abc').tolist()
[97, 98, 99]
>>> import array
>>> a = array.array('d', [1.1, 2.2, 3.3])
>>> m = memoryview(a)
>>> m.tolist()
[1.1, 2.2, 3.3]

tolist() поддерживаются все односимвольные собственные форматы в structсинтаксисе модуля, а также многомерные представления.

toreadonly( )

Возвращет версию объекта memoryview только для чтения. Исходный объект memoryview не изменился.

>>> m = memoryview(bytearray(b'abc'))
>>> mm = m.toreadonly()
>>> mm.tolist()
[89, 98, 99]
>>> mm[0] = 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot modify read-only memory
>>> m[0] = 43
>>> mm.tolist()
[43, 98, 99]

release( )

Освобождает базовый буфер, предоставляемый объектом memoryview. Многие объекты выполняют особые действия, когда на них удерживается представление (например, bytearrayвременно запрещает изменение размера); поэтому вызов release() удобен, чтобы как можно скорее снять эти ограничения (и освободить все зависшие ресурсы).

После того, как этот метод был вызван, любая дальнейшая операция с представлением вызывает ValueError(кроме release()самого себя, который может вызываться несколько раз):

>>> m = memoryview(b'abc')
>>> m.release()
>>> m[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: operation forbidden on released memoryview object

Протокол управления контекстом можно использовать для аналогичного эффекта, используя with оператор:

>>> with memoryview(b'abc') as m:
... m[0]
...
97
>>> m[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: operation forbidden on released memoryview object

cast( format [, shape ] )

Приведите изображение из памяти в новый формат или форму. По умолчанию для shape установлено значение [byte_length//new_itemsize], что означает, что вид результатов будет одномерным. Возвращаемое значение - новое представление памяти, но сам буфер не копируется. Поддерживаемые преобразования: 1D -> C- смежные и C-смежные -> 1D.

Формат назначения ограничен собственным struct синтаксисом с одним элементом . Один из форматов должен быть байтовым («B», «b» или «c»). Длина результата в байтах должна быть такой же, как и исходная длина.

Преобразование 1D / long в 1D / беззнаковые байты:

>>> import array
>>> a = array.array('l', [1,2,3])
>>> x = memoryview(a)
>>> x.format
'l'
>>> x.itemsize
8
>>> len(x)
3
>>> x.nbytes
24
>>> y = x.cast('B')
>>> y.format
'B'
>>> y.itemsize
1
>>> len(y)
24
>>> y.nbytes
24

Преобразование байтов 1D / без знака в 1D / char:

>>> b = bytearray(b'zyz')
>>> x = memoryview(b)
>>> x[0] = b'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: memoryview: invalid value for format "B"
>>> y = x.cast('c')
>>> y[0] = b'a'
>>> b
bytearray(b'ayz')

Преобразование 1D / байтов в 3D / int в 1D / подписанный char:

>>> import struct
>>> buf = struct.pack("i"*12, *list(range(12)))
>>> x = memoryview(buf)
>>> y = x.cast('i', shape=[2,2,3])
>>> y.tolist()
[[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]]
>>> y.format
'i'
>>> y.itemsize
4
>>> len(y)
2
>>> y.nbytes
48
>>> z = y.cast('b')
>>> z.format
'b'
>>> z.itemsize
1
>>> len(z)
48
>>> z.nbytes
48

Преобразование 1D / unsigned long в 2D / unsigned long:

>>> buf = struct.pack("L"*6, *list(range(6)))
>>> x = memoryview(buf)
>>> y = x.cast('L', shape=[2,3])
>>> len(y)
2
>>> y.nbytes
48
>>> y.tolist()
[[0, 1, 2], [3, 4, 5]]

obj

Базовый объект memoryview:

>>> b = bytearray(b'xyz')
>>> m = memoryview(b)
>>> m.obj is b
True

nbytes

nbytes == product(shape) * itemsize == len(m.tobytes()). Это количество места в байтах, которое массив будет использовать в непрерывном представлении. Это не обязательно равно len(m):

>>> import array
>>> a = array.array('i', [1,2,3,4,5])
>>> m = memoryview(a)
>>> len(m)
5
>>> m.nbytes
20
>>> y = m[::2]
>>> len(y)
3
>>> y.nbytes
12
>>> len(y.tobytes())
12

Многомерные массивы:

>>> import struct
>>> buf = struct.pack("d"*12, *[1.5*x for x in range(12)])
>>> x = memoryview(buf)
>>> y = x.cast('d', shape=[3,4])
>>> y.tolist()
[[0.0, 1.5, 3.0, 4.5], [6.0, 7.5, 9.0, 10.5], [12.0, 13.5, 15.0, 16.5]]
>>> len(y)
3
>>> y.nbytes
96

readonly

Логическое значение, указывающее, доступна ли память только для чтения.

format

Строка, содержащая формат (в struct стиле модуля) для каждого элемента в представлении. Просмотр памяти может быть создан из экспортеров со строками произвольного формата, но некоторые методы (например tolist()) ограничены собственными форматами одиночных элементов.

Изменено в версии 3.3: формат 'B'теперь обрабатывается в соответствии с синтаксисом модуля структуры. Это значит что .memoryview(b'abc')[0] == b'abc'[0] == 97

itemsize

Размер в байтах каждого элемента memoryview:

>>> import array, struct
>>> m = memoryview(array.array('H', [32000, 32001, 32002]))
>>> m.itemsize
2
>>> m[0]
32000
>>> struct.calcsize('H') == m.itemsize
True

ndim

Целое число, указывающее, сколько измерений многомерного массива представляет память.

shape

Кортеж целых чисел, длина которого ndim задает форму памяти в виде N-мерного массива.

strides

Кортеж целых чисел, длина которого ndim задает размер в байтах для доступа к каждому элементу каждого измерения массива.

suboffsets

Используется внутри для массивов в стиле PIL. Значение носит исключительно информационный характер.

c_contiguous

Логическое значение, указывающее, является ли память C- непрерывной .

f_contiguous

Логическое значение, указывающее, является ли память непрерывной в Фортране.

contiguous

Логическое значение, указывающее, является ли память непрерывной .

Типы наборов - set, frozenset

Набор объект представляет собой неупорядоченный набор различных hashable объектов. Обычно используется проверка принадлежности, удаление дубликатов из последовательности и вычисление математических операций, таких как пересечение, объединение, разность и симметричная разность. (Для других контейнеров см встроенный в dict, list, и tuple классы, и collections модуль.)

Как и другие коллекции, наборы поддержки x in set, len(set) и for x in set. Будучи неупорядоченной коллекцией, наборы не записывают позицию элемента или порядок вставки. Соответственно, наборы не поддерживают индексацию, нарезку или другое поведение, подобное последовательности.

В настоящее время существует два встроенных типа наборов: set и frozenset. set. Содержание может быть изменено с помощью методов add() и remove(). Поскольку он изменяемый, он не имеет хэш-значения и не может использоваться как ключ словаря или как элемент другого набора. frozenset Тип неизменен и hashable - его содержимое не может быть изменен после его создания; поэтому его можно использовать как ключ словаря или как элемент другого набора.

Непустые наборы (не замороженные наборы) можно создать, поместив список элементов, разделенных запятыми, в фигурные скобки, например:, в дополнение к конструктору.{'jack', 'sjoerd'}set

Конструкторы для обоих классов работают одинаково:

class set( [ iterable ] )

class frozenset( [ iterable ] )

Возвращает новый объект set или frozenset, элементы которого взяты из итерации . Элементы набора должны быть хешируемыми . Для представления наборов наборов внутренние наборы должны быть frozenset объектами. Если итерабельность не указана, возвращается новый пустой набор.

Экземпляры set и frozenset обеспечивают следующие операции:

len(s)

Возвращает количество элементов в наборе s ( количество элементов s ).

x in s

проверяет x на принадлежность к s .

x not in s

Проверяет x на непринадлежность к s .

isdisjoint( other )

Возвращает, Trueесли набор не имеет общих элементов с другими . Множества не пересекаются тогда и только тогда, когда их пересечение - пустое множество.

issubset( other )

set <= other

Проверяет, все ли элементы в наборе являются другими .

set < other

Проверяет, является ли набор правильным подмножеством other , то есть .set <= other and set != other

issuperset( other )

set >= other

Проверяет, есть ли в наборе все остальные элементы .

set > other

Проверяет, является ли набор подходящим надмножеством других , то есть .set >= other and set != other

union( * other )

set | other | ...

Возвращает новый набор с элементами из набора и всеми остальными.

intersection( * other )

set & other & ...

Возвращает новый набор с элементами, общими для набора и всех остальных.

difference( * other )

set - other - ...

Возвращает новый набор с элементами в наборе, которых нет в других.

symmetric_difference( other )

set ^ other

Вовзращает новый набор с элементами либо в наборе, либо в другом, но не с обоими.

copy( )

Возвращает неглубокую копию набора.

Обратите внимание, что union(), intersection(), difference(), и symmetric_difference(), issubset() и issuperset()методы будут принимать любую итерацию в качестве аргумента. Напротив, их аналоги на основе операторов требуют, чтобы их аргументы были установлены. Это исключает подверженные ошибкам конструкции, например, в пользу более удобочитаемых .set('abc') & 'cbs'set('abc').intersection('cbs')

Оба set и frozenset поддерживают набор для сравнения. Два набора равны тогда и только тогда, когда каждый элемент каждого набора содержится в другом (каждый является подмножеством другого). Набор меньше другого набора тогда и только тогда, когда первый набор является надлежащим подмножеством второго набора (является подмножеством, но не равен). Набор больше другого набора тогда и только тогда, когда первый набор является надлежащим надмножеством второго набора (является надмножеством, но не равен).

Экземпляры set сравниваются с экземплярами на frozenset основе их членов. Например, set('abc') == frozenset('abc')возвращает True и также поступает set('abc') in set([frozenset('abc')]).

Сравнение подмножества и равенства не распространяется на функцию полного упорядочения. Например, любые два непустых множества непересекающихся не равны и не являются подмножествами друг друга, так что все из следующего возвращения False: a<b, a==bили a>b.

Поскольку наборы определяют только частичное упорядочение (отношения подмножеств), выходные данные list.sort()метода не определены для списков наборов.

Элементы набора, такие как ключи словаря, должны быть хешируемыми .

Бинарные операции, которые смешивают set экземпляры с frozenset возвращением типа первого операнда. Например: frozenset('ab') | set('bc') возвращает экземпляр frozenset.

В следующей таблице перечислены доступные операции, set которые не применяются к неизменяемым экземплярам frozenset:

update( * other )

set |= other | ...

Обновляет набор, добавив элементы из всех остальных.

intersection_update( * other )

set &= other & ...

Обновляет набор, сохранив только элементы, найденные в нем и все остальные.

difference_update( * other )

set -= other | ...

Оюбновляет набор, удалив элементы, найденные в других.

symmetric_difference_update( other )

set ^= other

Обновляет набор, сохранив только элементы, найденные в любом наборе, но не в обоих.

add( elem )

Добавляет элемент elem в набор.

remove( elem )

Удаляет элемент elem из набора. Возникает, KeyError, если элемента нет в наборе.

discard( elem )

Удаляет элемент elem из набора, если он присутствует.

pop( )

Удаляет и возвращает произвольный элемент из набора. Поднимается, KeyError если набор пуст.

clear( )

Убирвет все элементы из набора.

Обратите внимание, что update(), intersection_update(), difference_update()и symmetric_difference_update()методы будут принимать любую итерацию в качестве аргумента.

Обратите внимание, что в elem аргумент __contains__(), remove()и discard()методы могут быть множеством. Для поддержки поиска эквивалентного frozenset из elem создается временный .

Заключение

Да, это еще не все

Пост создан для тг-канала @coolcoders