Язык программирования Python.

Агрегация.

Контейнеры.

Под контейнером обычно понимают объект, основным назначением которого является хранение и обеспечение доступа к другим объектам. Контейнеры реализуют отношение «HAS–A» («ИМЕЕТ») между объектами. Встроенные типы, список и словарь — яркие примеры контейнеров. Можно построить собственные типы контейнеров, которые будут иметь свою логику доступа к хранимым объектам. В контейнере хранятся не сами объекты, а ссылки на них.

Для практических нужд в Python обычно хватает встроенных контейнеров (словаря и списка), но если это необходимо, можно создать и другие. Ниже приведен класс Стек, реализованный на базе списка:

Class Stack:

 def __init__(self):

  """Инициализация стека""".

  self._stack = [].

 def top(self):

  """Возвратить вершину стека (не снимая)""".

  return self._stack[-1].

 def pop(self):

  """Снять со стека элемент""".

  return self._stack.pop().

 def push(self, x):

  """Поместить элемент на стек""".

  self._stack.append(x).

 def __len__(self):

  """Количество элементов в стеке""".

  return len(self._stack).

 def __str__(self):

  """Представление в виде строки""".

  return " : ".join(["%s" % e for e in self._stack]).

Использование:

>>> s = Stack().

>>> s.push(1).

>>> s.push(2).

>>> s.push("abc").

>>> print s.pop().

Abc.

>>> print len(s).

2.

>>> print s.

1 : 2.

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

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

Итераторы.

Итераторы — это объекты, которые предоставляют последовательный доступ к элементам контейнера (или генерируемым «на лету» объектам). Итератор позволяет перебирать элементы, абстрагируясь от реализации того контейнера, откуда он их берет (если этот контейнер вообще есть).

В следующем примере приведен итератор, выдающий значения из списка по принципу «считалочки» по N:

Class Zahlreim:

 def __init__(self, lst, n):

  self.n = n.

  self.lst = lst.

  self.current = 0.

 def __iter__(self):

  return self.

 def next(self):

  if self.lst:

   self.current = (self.current + self.n — 1) % len(self.lst).

   return self.lst.pop(self.current).

  else:

   raise StopIteration.

Print range(1, 11).

For i in Zahlreim(range(1, 11), 5):

 print i,

Программа выдаст.

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].

5 10 6 2 9 8 1 4 7 3.

В этой программе делегировано управление доступом к элементам списка (или любого другого контейнера, имеющего метод pop(n) для взятия и удаления n–го элемента) классу–итератору. Итератор должен иметь метод next() и возбуждать исключение StopIteration по завершении итераций. Кроме того, метод __iter__() должен выдавать итератор по экземпляру класса (в данном случае итератор — он сам ( self)).

В настоящее время итераторы приобретают все большее значение, и о них много говорилось в лекции по функциональному программированию.