Лучший подход с динамическими классами с помощью Python globals ()

Семантика параллелизма зависит от фактической реализации связующего. Например, в случае связывателя Кафки, когда вы устанавливаете параллелизм, это значение будет передано в базовый MessageListenerContainer. Допустим, ваше потребительское приложение использует тему из 3 разделов, и вы установите значение concurrency в 3. Это создаст 3 потока в контейнере, в котором каждый из них обрабатывает один раздел из темы (В На самом деле, в случае связующего Kafka, 3 контейнера слушателя будут созданы за кулисами). Если в теме больше разделов, чем параллельных потоков, то разделы будут распределены по различным потокам. Та же самая семантика применима и к связующему с Кроликом, хотя его фактическая реализация может немного отличаться внутри страны.

6
задан hmason 21 October 2008 в 14:41
поделиться

3 ответа

Дефект с этим подходом - то, что он может дать пользователю способность к к больше, чем, Вы хотите их к. Они могут вызвать любую функцию единственного параметра в том пространстве имен только путем обеспечения имени. Можно помочь принять меры против этого с несколькими проверками (например, isinstance (SomeBaseClass, theClass), но, вероятно, лучше для предотвращения этого подхода. Другой недостаток - то, что это ограничивает Ваше размещение класса. Если Вы закончите с десятками таких классов и решите сгруппировать их в модули, то Ваш код поиска прекратит работать.

У Вас есть несколько альтернативных опций:

  1. Создайте явное отображение:

     class_lookup = {'Class1' : Class1, ... }
     ...
     result = class_lookup[className](param).html
    

    хотя это имеет недостаток, что необходимо переупорядочить все классы.

  2. Вложите классы в объеме включения. Например, определите их в их собственном модуле, или во внешнем классе:

    class Namespace(object):
        class Class1(object):
            ...
        class Class2(object):
            ...
    ...
    result = getattr(Namespace, className)(param).html
    

    Вы действительно непреднамеренно выставляете несколько дополнительных переменных класса здесь хотя (__ базируется __, __ getattribute __ и т.д.) - вероятно, не годный для использования, но не прекрасный.

  3. Создайте поиск dict из дерева подкласса. Заставьте все свои классы наследоваться единственному базовому классу. Когда все классы были созданы, исследуют все базовые классы и заполняют dict от них. Это имеет преимущество, что можно определить классы где угодно (например, в отдельных модулях), и пока Вы создаете реестр, в конце концов, создаются, Вы найдете их.

    def register_subclasses(base):
        d={}
        for cls in base.__subclasses__():
            d[cls.__name__] = cls
            d.update(register_subclasses(cls))
        return d
    
    class_lookup = register_subclasses(MyBaseClass)
    

    Более усовершенствованная вариация на вышеупомянутое должна использовать саморегистрирующиеся классы - создают метакласс, чем автоматически регистры любые созданные классы в dict. Это - вероятно, излишество для этого случая - его полезное в некоторых сценариях "пользовательских плагинов" все же.

6
ответ дан 10 December 2019 в 00:46
поделиться

Другой способ создать карту между именами классов и классами:

При определении классов добавьте атрибут к любому классу, что Вы хотите вставить справочную таблицу, например:

class Foo:
    lookup = True
    def __init__(self, params):
        # and so on

После того как это сделано, создавание карты поиска:

class_lookup = zip([(c, globals()[c]) for c in dir() if hasattr(globals()[c], "lookup")])
0
ответ дан 10 December 2019 в 00:46
поделиться

В первую очередь, это кажется, что можно изобретать велосипед немного... большинство веб-платформ Python (CherryPy/TurboGears - то, что я знаю), уже включают способ отправить запросы определенным классам на основе содержания URL или ввод данных пользователем.

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

Так, как первый шаг, Вы могли бы хотеть просто сделать словарь всех классов, которые Вы могли бы хотеть назвать:

dispatch = {'Foo': Foo, 'Bar': Bar, 'Bizbaz': Bizbaz}

Первоначально, это не будет иметь большую часть значения. Но поскольку Ваше веб-приложение растет, можно найти несколько преимуществ: (a) Вы не столкнетесь со столкновениями пространства имен, (b) использование globals() у Вас могут быть проблемы безопасности, где взломщик может, в сущности, получить доступ к любому глобальному символу в Вашей программе, если они могут найти способ ввести произвольное classname в Вашу программу, (c), если Вы когда-нибудь хотите иметь classname будьте чем-то другим, чем фактическое точное имя класса, с помощью собственного словаря будет более гибким, (d) Вы может заменить dispatch словарь с более - гибкий пользовательский класс, который делает доступ к базе данных или что-то как этот, если Вы находите потребность.

Проблемами безопасности является особенно выступ для веб-приложения. Выполнение globals()[variable] где variable вводится из веб-формы, просто напрашивается на неприятности.

4
ответ дан 10 December 2019 в 00:46
поделиться
Другие вопросы по тегам:

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