Я хочу настраиваемый python вызываемый. Класс против фабрики функций? - PullRequest
2 голосов
/ 10 апреля 2020

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

Python 's' Должен быть один - и, предпочтительно, только один - очевидный способ сделать это »подводит меня сюда.

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

Например, две мои попытки парсера с ограниченным диапазоном игрушек приведены ниже.

class Parser():
    def __init__(self, nType=int, nRange=None):
        self.nType = nType
        self.nRange = nRange
        self.__doc__ = 'class - range is {}'.format(str(nRange))

    def __call__(self, inStr):
        x = self.nType(inStr)
        if self.nRange:
            if not self.nRange[0] <= x <= self.nRange[1]:
                raise ValueError('{} is out of range (class)'.format(inStr))
        return x        

def parserFactory(nType=int, nRange=None):
    def parser(inStr):
        x = nType(inStr)
        if nRange:
            if not nRange[0] <= x <= nRange[1]:
                raise ValueError('{} is out of range (factory)'.format(inStr))
        return x
    parser.__doc__ = 'factory - range is {}'.format(str(nRange))
    return parser    

a = Parser()
b = Parser(nRange=(3,6), nType=float)
c = parserFactory(nType=float)
d = parserFactory(nRange=(3, 6))

for string in ['4', '14']:
    for x in [a,b,c,d,int]:
        print(x.__doc__[:35])
        try:
            print(string, x(string))
        except ValueError as error:
            print(error)

Оба делают то, что я хочу. Оба имеют более или менее одинаковую сложность и по сути одинаковые утверждения, хотя и в разном порядке. Фабрика немного короче. Я не ожидаю необходимости использовать какие-либо другие методы класса. Я не вижу четкого способа выбрать, что «лучше».

Является ли один или другой питон более c?

С большей или большей вероятностью меня столкнет тот или иной Сложность, если (когда) я пытаюсь изменить их непредвиденными способами?

Что делает большинство людей?

Я довольно неопытный программист. Я прочитал статью Википедии о «шаблоне фабричного метода» и тонкостях в ней go прямо над моей головой.

(правка) Прочитав комментарии, ответы и ссылки, я думаю, что одна из проблем заключается в том, что ни один не подходит. Вы не ожидаете, что в классе будет так мало методов, даже если это возможно. Вы не ожидаете, что функция будет нести атрибут, даже если это возможно. Поскольку синтаксис очень похож, вероятно, не имеет значения, какой я использую изначально, поскольку я могу переключаться без изменения поведения. (/ Редактирование)

1 Ответ

0 голосов
/ 10 апреля 2020

Вы можете думать о функциях как syntacti c sugar для классов с __init__ и __call__. Это также верно для генераторов против классов, менеджеров контекста против классов, ...

Если вы только передаете анализатор и вызываете его где-то (то есть выполняете функции), то вам следует использовать фабрику. Это также позволяет вам позже легко перейти на класс, ваша фабрика может просто вернуть класс.

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

Все, что сказано, в этом конкретном случае c, который вы показали здесь, я думаю, я бы использовал functools.partial

...