Альтернативное описание паттернов проектирования: iterator

в 4:19, , рубрики: python, образование, паттерны проектирования, метки: , ,

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

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

На нашем, осмысленном примере это означает, что мы вместо специализированной функции printAll класса FileSystem, которая распечатывала содержимое файловой системы, подставим более универсальную iteritems, возвращающую итератор.

Для удобства сравнения кода с базовым примером, он слева, добавлена картинка аля — diff.

Изображение - savepic.su — сервис хранения изображений

Сам код примера.

# -*- coding: utf-8 -*-

fileSystem = None

class File:
  def __init__(self, size):
    self.size = size
    self.ind = fileSystem.create(self)
    self.parent = None

  def name(self):
    if not self.parent:
      return ""
    else:
      return self.parent.getName(self.ind)

class Dir:
  def __init__(self):
    self.ind = fileSystem.create(self)
    self.parent = None
    self.container = {}

  def getName(self, ind):
    return self.name() + self.container[ind]

  def name(self):
    if not self.parent:
      return ""
    else:
      return self.parent.getName(self.ind) + "/"

  def size(self):
    return len(self.container)

  def add(self, name, file):
    file.parent = self
    self.container[file.ind] = name

class Root(Dir):
  def __init__(self):
    Dir.__init__(self)

  def name(self):
    return "/"

class Link:
  def __init__(self, link):
    self.link = link
    self.ind = fileSystem.create(self)
    self.parent = None

  def name(self):
    if not self.parent:
      return " -> " + self.link.name()
    else:
      return self.parent.getName(self.ind) + " -> " + self.link.name()

  def size(self):
    return 8

class FileSystem:
  def __init__(self):
    self.container = {}

  def create(self, file):
    ind = hash(file)
    self.container[ind] = file
    return ind

  def find(self, name):
    for value in self.container.itervalues():
      if value.name() == name:
        return value
    return None

  def iteritems(self):
    return self.container.itervalues()

if __name__ == "__main__":
  fileSystem = FileSystem()
  root = Root()
  etc = Dir()
  root.add("etc", etc)
  home = Dir()
  root.add("home", home)
  user = Dir()
  home.add("user", user)
  user.add("readme.txt", File(1177))
  user.add(".etc", Link(etc))
  for value in fileSystem.iteritems():
    if isinstance(value, File):
      print "file: %8d %s" % (value.size, value.name())
    elif isinstance(value, Dir):
      print " dir: %8d %s" % (value.size(), value.name())
    elif isinstance(value, Link):
      print "link: %8d %s" % (value.size(), value.name())
  print "find('/home/user')=", fileSystem.find("/home/user")
  print "find('/home/user/')=", fileSystem.find("/home/user/")

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

 dir:        2 /home/user/
file:     1177 /home/user/readme.txt
link:        8 /home/user/.etc -> /etc/
 dir:        2 /
 dir:        0 /etc/
 dir:        1 /home/
find('/home/user')= None
find('/home/user/')= <__main__.Dir instance at 0x7f74ee8c3638>

Автор: bya

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js