Spec-Zone.ru › Python 3.6

collections — Типы контейнерных данных

Исходный код: Lib/collections/__init__.py

В этом модуле реализованы специализированные типы контейнеров, предоставляющие альтернативы встроенным контейнерам Python общего назначения, dict, list, set и tuple.

namedtuple()

функция-фабрика для создания подклассов кортежей с именованными полями

deque

подобный списку контейнер с быстрыми добавлениями и удалениями элементов с обоих концов

ChainMap

класс, подобный словарю, для создания единого представления нескольких словарей

Counter

подкласс словаря для подсчёта хешируемых объектов

OrderedDict

подкласс словаря, запоминающий порядок добавления элементов

defaultdict

подкласс словаря, вызывающий функцию-фабрику для предоставления пропущенных значений

UserDict

обёртка вокруг объектов словарей для более лёгкого создания подклассов словарей

UserList

обёртка вокруг объектов списков для более лёгкого создания подклассов списков

UserString

обёртка вокруг объектов строк для более лёгкого создания подклассов строк

Изменено в версии 3.3: Перемещено Абстрактные базовые классы коллекций в модуль collections.abc. Для обратной совместимости они по-прежнему видны в этом модуле.

8.3.1. Объекты ChainMap

Добавлена в версии 3.3.

Класс ChainMap предназначен для быстрого связывания нескольких словарей, чтобы их можно было обрабатывать как единое целое. Это часто намного быстрее, чем создание нового словаря и выполнение нескольких вызовов update().

Класс можно использовать для моделирования вложенных областей видимости и он полезен в шаблонизации.

class collections.ChainMap(*maps)

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

Внутренние отображения хранятся в списке. Этот список общедоступен и может быть обращён или обновлён с помощью атрибута maps. Других состояний нет.

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

Класс ChainMap использует ссылки на внутренние отображения. Поэтому, если одно из внутренних отображений обновляется, эти изменения будут отражены в ChainMap.

Поддерживаются все обычные методы словарей. Кроме того, есть атрибут maps, метод для создания новых подконтекстов и свойство для доступа ко всем отображениям, кроме первого:

maps

Список отображений, обновляемый пользователем. Список упорядочен от первого искомого до последнего искомого. Это единственное хранимое состояние и его можно изменить, чтобы изменить отображения, которые ищутся. Список всегда должен содержать по крайней мере одно отображение.

new_child(m=None)

Возвращает новый ChainMap, содержащий новое отображение, за которым следуют все отображения в текущем экземпляре. Если m указан, он становится новым отображением в начале списка отображений; если не указан, используется пустой словарь, так что вызов d.new_child() эквивалентен: ChainMap({}, *d.maps). Этот метод используется для создания подконтекстов, которые могут быть обновлены без изменения значений в родительских отображениях.

Изменено в версии 3.4: Добавлен необязательный параметр m.

parents

Свойство, возвращающее новый ChainMap, содержащий все отображения в текущем экземпляре, кроме первого. Это полезно для пропуска первого отображения в поиске. Сценарии использования аналогичны тем, которые для ключевого слова nonlocal, используемого в вложенных областях видимости. Сценарии использования также аналогичны тем, которые для встроенной функции super(). Ссылка на d.parents эквивалентна: ChainMap(*d.maps[1:]).

См. также

  • Класс MultiContext в пакете Enthought CodeTools имеет параметры для поддержки записи в любое отображение в цепочке.
  • Класс Context Django для шаблонизации — это только для чтения цепочка отображений. Он также имеет функции добавления и удаления контекстов, аналогичные методу new_child() и свойству parents().
  • Рецепт Nested Contexts имеет параметры для управления тем, применяются ли записи и другие изменения только к первому отображению или ко всем отображениям в цепочке.
  • Сильно упрощённая версия Chainmap только для чтения здесь.

8.3.1.1. ChainMap Примеры и рецепты

Этот раздел показывает различные подходы к работе с цепочками отображений.

Пример моделирования внутренней цепочки поиска Python:

import builtins
pylookup = ChainMap(locals(), globals(), vars(builtins))

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

import os, argparse

defaults = {'color': 'red', 'user': 'guest'}

parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
command_line_args = {k:v for k, v in vars(namespace).items() if v}

combined = ChainMap(command_line_args, os.environ, defaults)
print(combined['color'])
print(combined['user'])

Примеры шаблонов использования класса ChainMap для моделирования вложенных контекстов:

c = ChainMap()        # Create root context
d = c.new_child()     # Create nested child context
e = c.new_child()     # Child of c, independent from d
e.maps[0]             # Current context dictionary -- like Python's locals()
e.maps[-1]            # Root context -- like Python's globals()
e.parents             # Enclosing context chain -- like Python's nonlocals

d['x']                # Get first key in the chain of contexts
d['x'] = 1            # Set value in current context
del d['x']            # Delete from current context
list(d)               # All nested values
k in d                # Check all nested values
len(d)                # Number of nested values
d.items()             # All nested items
dict(d)               # Flatten into a regular dictionary

Класс ChainMap выполняет обновления (записи и удаления) только для первого отображения в цепочке, а обращения к ключам будут искать по всей цепочке. Однако если требуется глубокая запись и удаление, легко создать подкласс, который обновляет ключи, найденные глубже в цепочке:

class DeepChainMap(ChainMap):
    'Variant of ChainMap that allows direct updates to inner scopes'

    def __setitem__(self, key, value):
        for mapping in self.maps:
            if key in mapping:
                mapping[key] = value
                return
        self.maps[0][key] = value

    def __delitem__(self, key):
        for mapping in self.maps:
            if key in mapping:
                del mapping[key]
                return
        raise KeyError(key)

>>> d = DeepChainMap({'zebra': 'black'}, {'elephant': 'blue'}, {'lion': 'yellow'})
>>> d['lion'] = 'orange'         # update an existing key two levels down
>>> d['snake'] = 'red'           # new keys get added to the topmost dict
>>> del d['elephant']            # remove an existing key one level down
>>> d                            # display result
DeepChainMap({'zebra': 'black', 'snake': 'red'}, {}, {'lion': 'orange'})

8.3.2. Объекты Counter

Для удобного и быстрого подсчёта предоставляется инструмент подсчёта. Например:

>>> # Tally occurrences of words in a list
>>> cnt = Counter()
>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
...     cnt[word] += 1
>>> cnt
Counter({'blue': 3, 'red': 2, 'green': 1})

>>> # Find the ten most common words in Hamlet
>>> import re
>>> words = re.findall(r'\w+', open('hamlet.txt').read().lower())
>>> Counter(words).most_common(10)
[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
 ('you', 554),  ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]
class collections.Counter([iterable-or-mapping])

A Counter is a dict subclass for counting hashable objects. It is an unordered collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts. The Counter class is similar to bags or multisets in other languages.

Elements are counted from an iterable or initialized from another mapping (or counter):

>>> c = Counter()                           # a new, empty counter
>>> c = Counter('gallahad')                 # a new counter from an iterable
>>> c = Counter({'red': 4, 'blue': 2})      # a new counter from a mapping
>>> c = Counter(cats=4, dogs=8)             # a new counter from keyword args

Counter objects have a dictionary interface except that they return a zero count for missing items instead of raising a KeyError:

>>> c = Counter(['eggs', 'ham'])
>>> c['bacon']                              # count of a missing element is zero
0

Setting a count to zero does not remove an element from a counter. Use del to remove it entirely:

>>> c['sausage'] = 0                        # counter entry with a zero count
>>> del c['sausage']                        # del actually removes the entry

New in version 3.1.

Counter objects support three methods beyond those available for all dictionaries:

elements()

Return an iterator over elements repeating each as many times as its count. Elements are returned in arbitrary order. If an element’s count is less than one, elements() will ignore it.

>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> sorted(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']
most_common([n])

Return a list of the n most common elements and their counts from the most common to the least. If n is omitted or None, most_common() returns all elements in the counter. Elements with equal counts are ordered arbitrarily:

>>> Counter('abracadabra').most_common(3)  
[('a', 5), ('r', 2), ('b', 2)]
subtract([iterable-or-mapping])

Elements are subtracted from an iterable or from another mapping (or counter). Like dict.update() but subtracts counts instead of replacing them. Both inputs and outputs may be zero or negative.

>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> d = Counter(a=1, b=2, c=3, d=4)
>>> c.subtract(d)
>>> c
Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})

New in version 3.2.

The usual dictionary methods are available for Counter objects except for two which work differently for counters.

fromkeys(iterable)

This class method is not implemented for Counter objects.

update([iterable-or-mapping])

Elements are counted from an iterable or added-in from another mapping (or counter). Like dict.update() but adds counts instead of replacing them. Also, the iterable is expected to be a sequence of elements, not a sequence of (key, value) pairs.

Common patterns for working with Counter objects:

sum(c.values())                 # total of all counts
c.clear()                       # reset all counts
list(c)                         # list unique elements
set(c)                          # convert to a set
dict(c)                         # convert to a regular dictionary
c.items()                       # convert to a list of (elem, cnt) pairs
Counter(dict(list_of_pairs))    # convert from a list of (elem, cnt) pairs
c.most_common()[:-n-1:-1]       # n least common elements
+c                              # remove zero and negative counts

Several mathematical operations are provided for combining Counter objects to produce multisets (counters that have counts greater than zero). Addition and subtraction combine counters by adding or subtracting the counts of corresponding elements. Intersection and union return the minimum and maximum of corresponding counts. Each operation can accept inputs with signed counts, but the output will exclude results with counts of zero or less.

>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d                       # add two counters together:  c[x] + d[x]
Counter({'a': 4, 'b': 3})
>>> c - d                       # subtract (keeping only positive counts)
Counter({'a': 2})
>>> c & d                       # intersection:  min(c[x], d[x]) 
Counter({'a': 1, 'b': 1})
>>> c | d                       # union:  max(c[x], d[x])
Counter({'a': 3, 'b': 2})

Unary addition and subtraction are shortcuts for adding an empty counter or subtracting from an empty counter.

>>> c = Counter(a=2, b=-4)
>>> +c
Counter({'a': 2})
>>> -c
Counter({'b': 4})

New in version 3.3: Added support for unary plus, unary minus, and in-place multiset operations.

Примечание

Счётчики были разработаны в первую очередь для работы с положительными целыми числами для представления текущих подсчётов; однако, было предпринято всё возможное, чтобы не исключать ненужно случаи, требующие других типов или отрицательных значений. Чтобы помочь в этих случаях, в этом разделе документированы минимальные ограничения диапазона и типа.

  • Класс Counter сам по себе является подклассом словаря без ограничений на его ключи и значения. Значения предназначены для представления чисел, представляющих счёт, но вы можете хранить что угодно в поле значения.
  • Метод most_common() требует только, чтобы значения были упорядоченными.
  • Для операций на месте, таких как c[key] += 1, тип значения должен только поддерживать сложение и вычитание. Так что дроби, числа с плавающей запятой и десятичные дроби будут работать, и поддерживаются отрицательные значения. То же самое относится и к update() и subtract() , которые допускают отрицательные и нулевые значения как для входных, так и для выходных данных.
  • Методы мультимножества предназначены только для случаев использования с положительными значениями. Входные данные могут быть отрицательными или нулевыми, но создаются только выходные данные с положительными значениями. Ограничений типа нет, но тип значения должен поддерживать сложение, вычитание и сравнение.
  • Метод elements() требует целочисленных счётов. Он игнорирует нулевые и отрицательные счётчики.

См. также

  • Класс Bag в Smalltalk.
  • Статья Википедии о Мультимножествах.
  • Руководство по мультимножествам C++ с примерами.
  • Для математических операций над мультимножествами и их случаев использования см. Knuth, Donald. The Art of Computer Programming Volume II, Section 4.6.3, Exercise 19.
  • Чтобы перечислить все различные мультимножества заданного размера на заданном наборе элементов, см. itertools.combinations_with_replacement():

    map(Counter, combinations_with_replacement(‘ABC’, 2)) –> AA AB AC BB BC CC

8.3.3. объекты deque

class collections.deque([iterable[, maxlen]])

Возвращает новый объект deque, инициализированный слева направо (используя append()) данными из iterable. Если iterable не указан, новый deque пуст.

Deque — это обобщение стеков и очередей (название произносится как «дек» и является сокращением от «двухсторонней очереди»). Deque поддерживает потокобезопасные, эффективные с точки зрения памяти добавления и извлечения элементов с любой стороны deque с примерно одинаковой производительностью O(1) в любом направлении.

Хотя объекты list поддерживают аналогичные операции, они оптимизированы для быстрых операций с фиксированной длиной и несут затраты O(n) на перемещение памяти для операций pop(0) и insert(0, v) которые изменяют как размер, так и позицию базового представления данных.

Если maxlen не указан или равен None, deque может расти до произвольной длины. В противном случае deque ограничен указанной максимальной длиной. Когда ограниченный deque заполнен, при добавлении новых элементов соответствующее количество элементов отбрасывается с противоположного конца. Ограниченные deques предоставляют функциональность, аналогичную фильтру tail в Unix. Они также полезны для отслеживания транзакций и других наборов данных, где важна только последняя активность.

Объекты deque поддерживают следующие методы:

append(x)

Добавить x в правую сторону deque.

appendleft(x)

Добавить x в левую сторону deque.

clear()

Удалить все элементы из deque, оставив его длиной 0.

copy()

Создать поверхностную копию deque.

Новое в версии 3.5.

count(x)

Подсчитать количество элементов deque, равных x.

Новое в версии 3.2.

extend(iterable)

Расширить правую сторону deque, добавив элементы из iterable-аргумента.

extendleft(iterable)

Расширить левую сторону deque, добавив элементы из iterable. Обратите внимание, последовательность добавлений слева приводит к изменению порядка элементов в iterable-аргументе.

index(x[, start[, stop]])

Возвращает позицию x в deque (в или после индекса start и перед индексом stop). Возвращает первое совпадение или вызывает ValueError, если не найдено.

Новое в версии 3.5.

insert(i, x)

Вставить x в deque в позицию i.

Если вставка приведет к тому, что ограниченный deque вырастет за пределы maxlen, генерируется IndexError.

Новое в версии 3.5.

pop()

Удалить и вернуть элемент с правой стороны deque. Если элементов нет, генерируется IndexError.

popleft()

Удалить и вернуть элемент с левой стороны deque. Если элементов нет, генерируется IndexError.

remove(value)

Удалить первое вхождение value. Если не найдено, генерируется ValueError.

reverse()

Обратить элементы deque на месте и затем вернуть None.

Новое в версии 3.2.

rotate(n=1)

Повернуть deque на n шагов вправо. Если n отрицательно, повернуть влево.

Когда deque не пуст, поворот на один шаг вправо эквивалентен d.appendleft(d.pop()), а поворот на один шаг влево эквивалентен d.append(d.popleft()).

Объекты deque также предоставляют один атрибут только для чтения:

maxlen

Максимальный размер deque или None , если неограничен.

Новое в версии 3.1.

Помимо вышеперечисленного, deque поддерживает итерацию, сериализацию, len(d), reversed(d), copy.copy(d), copy.deepcopy(d), проверку на членство с помощью оператора in и индексированных ссылок, таких как d[-1]. Индексированный доступ — O(1) на обоих концах, но замедляется до O(n) посередине. Для быстрого произвольного доступа используйте списки.

Начиная с версии 3.5, deque поддерживает __add__(), __mul__(), и __imul__().

Пример:

>>> from collections import deque
>>> d = deque('ghi')                 # make a new deque with three items
>>> for elem in d:                   # iterate over the deque's elements
...     print(elem.upper())
G
H
I

>>> d.append('j')                    # add a new entry to the right side
>>> d.appendleft('f')                # add a new entry to the left side
>>> d                                # show the representation of the deque
deque(['f', 'g', 'h', 'i', 'j'])

>>> d.pop()                          # return and remove the rightmost item
'j'
>>> d.popleft()                      # return and remove the leftmost item
'f'
>>> list(d)                          # list the contents of the deque
['g', 'h', 'i']
>>> d[0]                             # peek at leftmost item
'g'
>>> d[-1]                            # peek at rightmost item
'i'

>>> list(reversed(d))                # list the contents of a deque in reverse
['i', 'h', 'g']
>>> 'h' in d                         # search the deque
True
>>> d.extend('jkl')                  # add multiple elements at once
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
>>> d.rotate(1)                      # right rotation
>>> d
deque(['l', 'g', 'h', 'i', 'j', 'k'])
>>> d.rotate(-1)                     # left rotation
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])

>>> deque(reversed(d))               # make a new deque in reverse order
deque(['l', 'k', 'j', 'i', 'h', 'g'])
>>> d.clear()                        # empty the deque
>>> d.pop()                          # cannot pop from an empty deque
Traceback (most recent call last):
    File "<pyshell#6>", line 1, in -toplevel-
        d.pop()
IndexError: pop from an empty deque

>>> d.extendleft('abc')              # extendleft() reverses the input order
>>> d
deque(['c', 'b', 'a'])

8.3.3.1. deque Рецепты

Этот раздел демонстрирует различные подходы к работе с deque.

Ограниченные deque предоставляют функциональность, аналогичную фильтру tail в Unix:

def tail(filename, n=10):
    'Return the last n lines of a file'
    with open(filename) as f:
        return deque(f, n)

Другой подход к использованию deque — поддерживать последовательность недавно добавленных элементов, добавляя вправо и извлекая слева:

def moving_average(iterable, n=3):
    # moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0
    # http://en.wikipedia.org/wiki/Moving_average
    it = iter(iterable)
    d = deque(itertools.islice(it, n-1))
    d.appendleft(0)
    s = sum(d)
    for elem in it:
        s += elem - d.popleft()
        d.append(elem)
        yield s / n

Метод rotate() предоставляет способ реализации срезов и удалений deque. Например, чисто Python-реализация срезов deque опирается на метод rotate() для позиционирования элементов, которые нужно извлечь:

def delete_nth(d, n):
    d.rotate(-n)
    d.popleft()
    d.rotate(n)

Для реализации срезов deque используйте аналогичный подход, применяя rotate() для перемещения целевого элемента влево deque. Удаляйте старые записи с помощью popleft(), добавляйте новые записи с помощью extend(), а затем инвертируйте вращение. С небольшими вариациями этого подхода легко реализовать манипуляции со стеком в стиле Forth, такие как dup, drop, swap, over, pick, rot, и roll.

8.3.4. Объекты defaultdict

class collections.defaultdict([default_factory[, ...]])

Возвращает новый объект, подобный словарю. defaultdict — это подкласс встроенного класса dict. Он переопределяет один метод и добавляет одну изменяемую переменную экземпляра. Остальная функциональность такая же, как у класса dict и здесь не документирована.

Первый аргумент задаёт начальное значение для атрибута default_factory; по умолчанию оно равно None. Все остальные аргументы обрабатываются так же, как если бы они были переданы в конструктор dict, включая ключевые аргументы.

Объекты defaultdict поддерживают следующий метод в дополнение к стандартным операциям с dict:

__missing__(key)

Если атрибут default_factory равен None, это вызывает исключение KeyError с ключом в качестве аргумента.

Если default_factory не равно None, он вызывается без аргументов для предоставления значения по умолчанию для данного ключа, это значение вставляется в словарь для ключа и возвращается.

Если вызов default_factory вызывает исключение, это исключение передаётся без изменений.

Этот метод вызывается методом __getitem__() класса dict, когда запрашиваемый ключ не найден; то, что он возвращает или вызывает, затем возвращается или вызывается методом __getitem__().

Обратите внимание, что __missing__() не вызывается для каких-либо операций, кроме __getitem__(). Это означает, что get() , как и обычные словари, вернёт None по умолчанию, а не использует default_factory.

Объекты defaultdict поддерживают следующую переменную экземпляра:

default_factory

Этот атрибут используется методом __missing__(); он инициализируется из первого аргумента конструктора, если он присутствует, или равен None, если отсутствует.

8.3.4.1. defaultdict Примеры

Используя list в качестве default_factory, легко сгруппировать последовательность пар «ключ-значение» в словарь списков:

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
...     d[k].append(v)
...
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

Когда ключ встречается впервые, он ещё не в отображении; поэтому автоматически создаётся запись, используя функцию default_factory, которая возвращает пустой list. Операция list.append() затем прикрепляет значение к новому списку. Когда ключи встречаются снова, поиск выполняется нормально (возвращая список для этого ключа), и операция list.append() добавляет ещё одно значение в список. Этот приём проще и быстрее, чем эквивалентный приём с использованием dict.setdefault():

>>> d = {}
>>> for k, v in s:
...     d.setdefault(k, []).append(v)
...
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

Установка default_factory на int делает defaultdict полезным для подсчёта (как мешок или мультимножество в других языках):

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
...     d[k] += 1
...
>>> sorted(d.items())
[('i', 4), ('m', 1), ('p', 2), ('s', 4)]

Когда буква встречается впервые, её нет в отображении, поэтому функция default_factory вызывает int() для обеспечения значения по умолчанию — ноль. Операция увеличения затем наращивает счётчик для каждой буквы.

Функция int(), которая всегда возвращает ноль, — это всего лишь частный случай постоянных функций. Более быстрый и гибкий способ создания постоянных функций — это использование лямбда-функции, которая может обеспечивать любое постоянное значение (а не только ноль):

>>> def constant_factory(value):
...     return lambda: value
>>> d = defaultdict(constant_factory('<missing>'))
>>> d.update(name='John', action='ran')
>>> '%(name)s %(action)s to %(object)s' % d
'John ran to <missing>'

Установка default_factory на set делает defaultdict полезным для создания словаря множеств:

>>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
>>> d = defaultdict(set)
>>> for k, v in s:
...     d[k].add(v)
...
>>> sorted(d.items())
[('blue', {2, 4}), ('red', {1, 3})]

8.3.5. namedtuple() — фабричная функция для кортежей с именованными полями

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

collections.namedtuple(typename, field_names, *, verbose=False, rename=False, module=None)

Возвращает новый подкласс кортежа с именем typename. Новый подкласс используется для создания объектов, похожих на кортежи, которые имеют поля, доступные по имени поля, а также индексируемые и итерируемые. Экземпляры подкласса также имеют полезную строку документации (с typename и field_names) и полезный метод __repr__(), который отображает содержимое кортежа в формате name=value.

field_names — это последовательность строк, таких как ['x', 'y']. В качестве альтернативы, field_names может быть одной строкой, в которой каждое имя поля отделено пробелами и/или запятыми, например 'x y' или 'x, y'.

Любое допустимое идентификатор Python может быть использовано для имени поля, за исключением имён, начинающихся с нижнего подчёркивания. Допустимые идентификаторы состоят из букв, цифр и подчёркиваний, но не начинаются с цифры или подчёркивания и не могут быть keyword, например, class, for, return, global, pass или raise.

Если rename равно True, недопустимые имена полей автоматически заменяются позиционными именами. Например, ['abc', 'def', 'ghi', 'abc'] преобразуется в ['abc', '_1', 'ghi', '_3'], устраняя ключевое слово def и дублируемое имя поля abc.

Если verbose равно True, определение класса печатается после его создания. Этот параметр устарел; проще напечатать атрибут _source.

Если module задано, атрибут __module__ именованного кортежа устанавливается в это значение.

Экземпляры именованных кортежей не имеют словарей на уровне экземпляра, поэтому они лёгкие и не требуют больше памяти, чем обычные кортежи.

Изменено в версии 3.1: Добавлена поддержка rename.

Изменено в версии 3.6: Параметры verbose и rename стали ключевыми аргументами.

Изменено в версии 3.6: Добавлен параметр module.

>>> # Basic example
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(11, y=22)     # instantiate with positional or keyword arguments
>>> p[0] + p[1]             # indexable like the plain tuple (11, 22)
33
>>> x, y = p                # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y               # fields also accessible by name
33
>>> p                       # readable __repr__ with a name=value style
Point(x=11, y=22)

Именованные кортежи особенно полезны для присвоения имён полям кортежей результатов, возвращаемых модулями csv или sqlite3:

EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')

import csv
for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
    print(emp.name, emp.title)

import sqlite3
conn = sqlite3.connect('/companydata')
cursor = conn.cursor()
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
for emp in map(EmployeeRecord._make, cursor.fetchall()):
    print(emp.name, emp.title)

В дополнение к методам, унаследованным от кортежей, именованные кортежи поддерживают три дополнительных метода и два атрибута. Чтобы избежать конфликтов с именами полей, имена методов и атрибутов начинаются с нижнего подчёркивания.

classmethod somenamedtuple._make(iterable)

Метод класса, который создаёт новый экземпляр из существующей последовательности или итерируемого объекта.

>>> t = [11, 22]
>>> Point._make(t)
Point(x=11, y=22)
somenamedtuple._asdict()

Возвращает новый словарь OrderedDict, который сопоставляет имена полей с их соответствующими значениями:

>>> p = Point(x=11, y=22)
>>> p._asdict()
OrderedDict([('x', 11), ('y', 22)])

Изменено в версии 3.1: Возвращает OrderedDict вместо обычного dict.

somenamedtuple._replace(**kwargs)

Возвращает новый экземпляр именованного кортежа, заменяющий указанные поля новыми значениями:

>>> p = Point(x=11, y=22)
>>> p._replace(x=33)
Point(x=33, y=22)

>>> for partnum, record in inventory.items():
...     inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now())
somenamedtuple._source

Строка с исходным кодом на чистом Python, используемым для создания класса именованного кортежа. Исходный код делает именованный кортеж самодокументирующимся. Его можно вывести на печать, выполнить с помощью exec() или сохранить в файл и импортировать.

Новое в версии 3.3.

somenamedtuple._fields

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

>>> p._fields            # view the field names
('x', 'y')

>>> Color = namedtuple('Color', 'red green blue')
>>> Pixel = namedtuple('Pixel', Point._fields + Color._fields)
>>> Pixel(11, 22, 128, 255, 0)
Pixel(x=11, y=22, red=128, green=255, blue=0)

Для получения поля, имя которого хранится в строке, используйте функцию getattr():

>>> getattr(p, 'x')
11

Для преобразования словаря в именованный кортеж используйте оператор двойной звёздочки (как описано в Развертывание списков аргументов):

>>> d = {'x': 11, 'y': 22}
>>> Point(**d)
Point(x=11, y=22)

Поскольку именованный кортеж — это обычный класс Python, легко добавить или изменить функциональность с помощью подкласса. Вот как добавить вычисляемое поле и формат вывода с фиксированной шириной:

>>> class Point(namedtuple('Point', ['x', 'y'])):
...     __slots__ = ()
...     @property
...     def hypot(self):
...         return (self.x ** 2 + self.y ** 2) ** 0.5
...     def __str__(self):
...         return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)

>>> for p in Point(3, 4), Point(14, 5/7):
...     print(p)
Point: x= 3.000  y= 4.000  hypot= 5.000
Point: x=14.000  y= 0.714  hypot=14.018

Подкласс, показанный выше, устанавливает __slots__ в пустой кортеж. Это помогает поддерживать низкие требования к памяти, предотвращая создание словарей экземпляров.

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

>>> Point3D = namedtuple('Point3D', Point._fields + ('z',))

Документацию можно настроить, выполнив прямые назначения в поля __doc__:

>>> Book = namedtuple('Book', ['id', 'title', 'authors'])
>>> Book.__doc__ += ': Hardcover book in active collection'
>>> Book.id.__doc__ = '13-digit ISBN'
>>> Book.title.__doc__ = 'Title of first printing'
>>> Book.authors.__doc__ = 'List of authors sorted by last name'

Изменено в версии 3.5: Документация по свойствам стала изменяемой.

Значения по умолчанию можно реализовать, используя _replace() для настройки экземпляра-прототипа:

>>> Account = namedtuple('Account', 'owner balance transaction_count')
>>> default_account = Account('<owner name>', 0.0, 0)
>>> johns_account = default_account._replace(owner='John')
>>> janes_account = default_account._replace(owner='Jane')

См. также

  • Рецепт абстрактного базового класса именованного кортежа с примесью метакласса Яна Калишевского. Кроме того, что он предоставляет абстрактный базовый класс для именованных кортежей, он также поддерживает альтернативный конструктор на основе метакласса, который удобен для случаев, когда именованные кортежи наследуются.
  • См. types.SimpleNamespace() для изменяемого пространства имён, основанного на базовом словаре, а не на кортеже.
  • См. typing.NamedTuple() для способа добавления подсказок типов для именованных кортежей.

8.3.6. Объекты OrderedDict

Обычные словари, но запоминают порядок вставки элементов. При итерации по упорядоченному словарю элементы возвращаются в порядке добавления ключей.

class collections.OrderedDict([items])

Возвращает экземпляр подкласса dict, поддерживающий обычные методы dict. OrderedDict — это dict, который запоминает порядок вставки ключей. Если новая запись перезаписывает существующую запись, исходное положение вставки остается неизменным. Удаление записи и повторная вставка поместят её в конец.

Новое в версии 3.1.

popitem(last=True)

Метод popitem() для упорядоченных словарей возвращает и удаляет пару (ключ, значение). Пары возвращаются в порядке LIFO, если last равно true, или FIFO, если false.

move_to_end(key, last=True)

Перемещает существующий ключ в конец или начало упорядоченного словаря. Элемент перемещается в конец, если last равно true (по умолчанию), или в начало, если last равно false. Вызывает KeyError, если ключ не существует:

>>> d = OrderedDict.fromkeys('abcde')
>>> d.move_to_end('b')
>>> ''.join(d.keys())
'acdeb'
>>> d.move_to_end('b', last=False)
>>> ''.join(d.keys())
'bacde'

Новое в версии 3.2.

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

Тесты равенства между объектами OrderedDict чувствительны к порядку и реализуются как list(od1.items())==list(od2.items()). Тесты равенства между объектами OrderedDict и другими объектами Mapping не учитывают порядок, как и обычные словари. Это позволяет использовать объекты OrderedDict везде, где используется обычный словарь.

Изменено в версии 3.5: Просмотры элементов, ключей и значений виды OrderedDict теперь поддерживают обратную итерацию с помощью reversed().

Изменено в версии 3.6: С принятием PEP 468, порядок сохраняется для именованных аргументов, переданных конструктору OrderedDict и его методу update().

8.3.6.1. OrderedDict Примеры и рецепты

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

>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}

>>> # dictionary sorted by key
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

>>> # dictionary sorted by length of the key string
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])

Новые отсортированные словари сохраняют свой порядок сортировки при удалении записей. Но при добавлении новых ключей ключи добавляются в конец, и сортировка не сохраняется.

Также легко создать вариант упорядоченного словаря, который запоминает порядок последней вставки ключей. Если новая запись перезаписывает существующую запись, исходное положение вставки изменяется и перемещается в конец:

class LastUpdatedOrderedDict(OrderedDict):
    'Store items in the order the keys were last added'

    def __setitem__(self, key, value):
        if key in self:
            del self[key]
        OrderedDict.__setitem__(self, key, value)

Упорядоченный словарь можно объединить с классом Counter, чтобы счётчик запоминал порядок, в котором элементы встречаются впервые:

class OrderedCounter(Counter, OrderedDict):
    'Counter that remembers the order elements are first encountered'

    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))

    def __reduce__(self):
        return self.__class__, (OrderedDict(self),)

8.3.7. Объекты UserDict

Класс UserDict выступает в качестве оболочки вокруг объектов словарей. Необходимость в этом классе частично устранена возможностью непосредственного наследования от dict; однако, этот класс может быть проще в использовании, поскольку базовый словарь доступен в качестве атрибута.

class collections.UserDict([initialdata])

Класс, имитирующий словарь. Содержимое экземпляра хранится в обычном словаре, доступном через атрибут data экземпляров UserDict. Если задано initialdata, data инициализируется его содержимым; обратите внимание, что ссылка на initialdata не сохраняется, что позволяет использовать его для других целей.

Помимо поддержки методов и операций отображений, экземпляры UserDict обеспечивают следующий атрибут:

data

Реальный словарь, используемый для хранения содержимого класса UserDict.

8.3.8. Объекты UserList

Этот класс действует как оболочка вокруг объектов списков. Это полезный базовый класс для ваших собственных спископодобных классов, которые могут наследовать от них и переопределять существующие методы или добавлять новые. Таким образом, можно добавить новые поведения к спискам.

Необходимость в этом классе частично устранена возможностью непосредственного наследования от list; однако, этот класс может быть проще в использовании, поскольку базовый список доступен в качестве атрибута.

END_OF_DOCUMENT_MARKER
class collections.UserList([list])

Класс, имитирующий список. Содержимое экземпляра хранится в обычном списке, доступном через атрибут data экземпляров UserList. Содержимое экземпляра изначально устанавливается в копию list, по умолчанию — пустой список []. list может быть любым итерируемым объектом, например, реальным списком Python или объектом UserList.

Помимо поддержки методов и операций изменяемых последовательностей, экземпляры UserList предоставляют следующий атрибут:

data

Реальный объект list, используемый для хранения содержимого класса UserList.

Требования к подклассам: От подклассов UserList ожидается наличие конструктора, который может быть вызван без аргументов или с одним аргументом. Операции со списками, возвращающие новую последовательность, пытаются создать экземпляр фактического класса реализации. Для этого предполагается, что конструктор может быть вызван с одним параметром, который является объектом последовательности, используемым в качестве источника данных.

Если производному классу не требуется соответствовать этому требованию, все специальные методы, поддерживаемые этим классом, необходимо переопределить; для получения информации о методах, которые необходимо предоставить в этом случае, обратитесь к исходному коду.

8.3.9. Объекты UserString

Класс UserString действует как обёртка вокруг строковых объектов. Необходимость в этом классе частично исчезла благодаря возможности непосредственного подклассирования от str; однако, с этим классом работать может быть проще, поскольку базовая строка доступна как атрибут.

class collections.UserString([sequence])

Класс, имитирующий строковый или строковый объект Unicode. Содержимое экземпляра хранится в обычном строковом объекте, доступном через атрибут data экземпляров UserString. Содержимое экземпляра изначально устанавливается в копию sequence. sequence может быть экземпляром bytes, str, UserString (или подклассом) или произвольной последовательностью, которая может быть преобразована в строку с помощью встроенной функции str().

Изменено в версии 3.5: Новые методы __getnewargs__, __rmod__, casefold, format_map, isprintable, и maketrans.

© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.6/library/collections.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API