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

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

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

Interpreter — решает часто встречающуюся, но подверженную изменениям, задачу.

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

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

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

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

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

import re

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):
    pattern = re.compile(name)
    r = []
    for value in self.container.itervalues():
      if pattern.search(value.name()):
        r.append(value.name())
    return r

  def printAll(self):
    for value in self.container.itervalues():
      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())

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))
  fileSystem.printAll()
  print "find('/home/user')=", fileSystem.find("/home/user")
  print "find(r'.*.txt$')=", fileSystem.find(r".*.txt$")

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

 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')= ['/home/user/', '/home/user/readme.txt', '/home/user/.etc -> /etc/']
find(r'.*.txt$')= ['/home/user/readme.txt']

Автор: bya

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


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