Как я могу создать только один экземпляр класса в зависимости от индекса в Python?

#python #dictionary #instance

Вопрос:

У меня есть функция, которая позволяет создавать экземпляр автоматов по заданному индексу. Пользователь выбирает опцию из меню, и индекс выбранной строки определяет используемые автоматы.

 def create_automata(idx, board):
    n_automatas = {
        0: GameOfLife(board),
        1: LangtonAnt(board, (board.height // 2) - 4, board.width // 2),
        2: BrianBrain(board),
        3: DayNight(board)
    }

    return n_automatas[idx]
 

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

Как я могу вернуть автоматы, не создавая больше экземпляров, чем мне нужно (без использования операторов if/elif)?

Комментарии:

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

2. В a нет ничего плохого dict ; if утверждение в худшем случае требует idx проверки всех возможных значений, прежде чем найти правильный случай.

3. @G. Андерсон @Чепнер Да, if утверждения определенно будут работать, но в будущем я планирую добавить как можно больше автоматов, так что иметь 100-строчные if/else утверждения было бы очень утомительно и скучно. Спасибо!

Ответ №1:

Один из простых способов-хранить вызываемые объекты в словаре, а не создавать экземпляры объектов:

 def create_automata(idx, board):
    n_automatas = {
        0: GameOfLife,
        1: lambda board: LangtonAnt(board, (board.height // 2) - 4, board.width // 2),
        2: BrianBrain,
        3: DayNight,
    }

    return n_automatas[idx](board)
 

Обратите внимание, что этот код становится намного чище, если вы можете изменить свой LangtonAnt конструктор, чтобы он просто брал плату и выводил другие параметры самостоятельно (если все конструкторы имеют одинаковую подпись, нет необходимости специально заключать ее в a lambda ).

Комментарии:

1. Удивительно, как мы втроем выдали идентичный код с интервалом в несколько секунд друг от друга.

2. это почти похоже на то, что это очень хорошо проторенный путь, лол

Ответ №2:

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

Это известно как фабричный шаблон.

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

 automatas = {
    0: GameOfLife,
    1: lambda board: LangtonAnt(board, (board.height // 2) - 4, board.width // 2),
    2: BrianBrain,
    3: DayNight
}

return automatas[idx](board)