Используя конструктора базового класса как фабрика в Python?

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

(?:\b(?:this|is|a|string)\s*)+(?<!\s)

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

8
задан bialix 13 February 2009 в 10:03
поделиться

6 ответов

Я придерживался бы подхода функции фабрики. Это - очень стандартный Python и легкий читать и понять. Вы могли сделать это более универсальным для обработки большего количества опций несколькими способами такой как путем передачи в функции различителя и карте результатов к классам.

Если первый пример работает, это больше удачей, чем дизайном. Что, если Вы хотели иметь __init__ определенный в Вашем подклассе?

13
ответ дан 5 December 2019 в 04:58
поделиться

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

class Project(object):
  "Base class and factory."
  def __new__(cls, url):
    if is_url_local(url):
       return super(Project, cls).__new__(ProjectLocal, url) 
    else:
       return super(Project, cls).__new__(ProjectRemote, url) 

  def __init__(self, url):
    self.url = url
18
ответ дан 5 December 2019 в 04:58
поделиться

Следующие ссылки могут быть полезными: http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html#factory http://code.activestate.com/recipes/86900/

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

Функция фабрики обычно более проста (поскольку другие люди уже отправили),

Кроме того, это не хорошая идея установить __, класс __ приписывает способ, которым Вы сделали.

Я надеюсь, что Вы находите ответ и ссылки полезными.

Всего наилучшего.

3
ответ дан 5 December 2019 в 04:58
поделиться

У меня обычно есть отдельный класс фабрики, чтобы сделать это. Таким образом, Вы не должны использовать метаклассы или присвоения на self.__class__

Я также стараюсь не помещать знание, о котором классы доступны для создания в фабрику. Скорее у меня есть все доступные классы, регистрируют себя жгут из прутьев фабрика во время импорта модуля. Давание там классифицирует и некоторая информация о том, когда выбрать этот класс к фабрике (это могло быть именем, regex или вызываемым (например, метод класса регистрирующегося класса)).

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

1
ответ дан 5 December 2019 в 04:58
поделиться

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

0
ответ дан 5 December 2019 в 04:58
поделиться

Да, как упомянул @scooterXL, фабричная функция - лучший подход в этом случае, но я хотел бы отметить случай для фабрик как classmethods.

Рассмотрим следующую иерархию классов:

class Base(object):

    def __init__(self, config):
        """ Initialize Base object with config as dict."""
        self.config = config

    @classmethod
    def from_file(cls, filename):
        config = read_and_parse_file_with_config(filename)
        return cls(filename)

class ExtendedBase(Base):

    def behaviour(self):
        pass # do something specific to ExtendedBase

Теперь вы можете создавать объекты Base из config dict и из config файла:

>>> Base({"k": "v"})
>>> Base.from_file("/etc/base/base.conf")

Но также, вы можете сделать то же самое с ExtendedBase бесплатно:

>>> ExtendedBase({"k": "v"})
>>> ExtendedBase.from_file("/etc/extended/extended.conf")

Таким образом, этот classmethod factory можно также рассматривать как вспомогательный конструктор.

2
ответ дан 5 December 2019 в 04:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: