В Python 3 вызов функции класса по имени перед инициализацией с наследованием

Цель:

  • B наследует от A.
  • A и B имеют фабричный метод create, который согласовывает различные типы ввода перед инициализацией фактического класса.
  • create вызывает различные методы создания create_general_1, create_general_2, create_specific_b_1 по их имени, указанному в виде строки.

Это мой текущий подход:

import sys

class A:
    def __init__(self, text):
        self.text = text
        print("I got initialized: {}".format(text))

    def create(create_method_str):
        # This is where it breaks:
        create_method = getattr(sys.modules[__name__], create_method_str)
        return create_method()

    def create_general_style_3():
        return A("a, #3")

class B(A):
    def create_b_style_1():
        return B("b, #1")

if __name__ == "__main__":
    B.create("create_b_style_1")

Это не удается со следующей ошибкой:

Трассировка (последний последний вызов): Файл "test.py", строка 22, в B.create("create_b_style_1") Файл "test.py", строка 10, в create create_method = getattr(sys.modules[__name__], create_method_str) AttributeError: объект «модуль» не имеет атрибута «create_b_style_1»

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

Большое спасибо!


person elke    schedule 29.10.2015    source источник
comment
У вас есть некоторые проблемы в коде, который у вас есть сейчас. Например, вы неправильно определяете методы. Каждый из них должен иметь self или cls в качестве первого аргумента, в зависимости от того, являются ли они методами экземпляра или класса. Вероятно, вы хотите, чтобы create был статическим методом. Возможно, вы также захотите, чтобы create вызывала подфункции, не передавая их имена в виде строк. Это кажется хрупким, хотя бы потому, что вы, возможно, захотите переименовать функции позже, не переучивая своих пользователей.   -  person Two-Bit Alchemist    schedule 30.10.2015
comment
Очень быстрый ответ, здорово! Я предложил ответ с вашей помощью. Что касается хрупкости: в какой-то момент пользовательский ввод необходимо будет сопоставить с внутренними методами. Это всегда будет хрупким, независимо от того, где происходит сопоставление. Обработку исключений можно легко интегрировать в текущее решение. Если вы знаете лучшее решение, я очень рад это слышать!   -  person elke    schedule 30.10.2015


Ответы (1)


Благодаря комментарию Two-Bit Alchemist я создал это решение, которое, кажется, работает нормально. Любые улучшения / другие предложения более чем приветствуются :)

Все хорошо объяснено здесь.

import sys

class A:
    def __init__(self, text):
        self.text = text
        print("I got initialized: {}".format(text))

    @classmethod
    def create(cls, create_method_str):
        create_method = getattr(cls, create_method_str)
        return create_method()

    @classmethod
    def create_general_style_3(cls):
        return cls("a, #3")

class B(A):
    @classmethod
    def create_b_style_1(cls):
        return cls("b, #1")

if __name__ == "__main__":
    B.create("create_b_style_1")
person elke    schedule 29.10.2015