Подтвердить что ты не робот

Как установить имена классов динамически?

У меня есть функция, которая создает классы, полученные из ее аргументов:

def factory(BaseClass) :
    class NewClass(BaseClass) : pass
    return NewClass

Теперь, когда я использую его для создания новых классов, все классы имеют одинаковые имена, и экземпляры выглядят так, как будто они имеют один и тот же тип:

NewA = factory(ClassA)
NewB = factory(ClassB)
print type(NewA()) # <class __main__.NewClass>
print type(NewB()) # <class __main__.NewClass>

Является ли правильное исправление для установки атрибута __name__ вручную?

NewA.__name__ = 'NewA'
print type(NewA()) # <class __main__.NewA>

Есть ли какие-то другие вещи, которые я должен устанавливать, пока я нахожусь на нем?

4b9b3361

Ответ 1

Да, настройка __name__ - правильная вещь; вам не нужно устанавливать что-либо еще для настройки имени класса.

Например:

def factory(BaseClass) :
    class NewClass(BaseClass): pass
    NewClass.__name__ = "factory_%s" % BaseClass.__name__
    return NewClass

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

Ответ 2

Проверьте, используя функцию type() с тремя аргументами. Следующий код создает новый класс "NewA" с object в качестве базового типа и без начальных атрибутов.

>>> type('NewA', (object,), {})
<class '__main__.NewA'>

Ответ 3

Обновление ответа от Гленна Мейнарда: В настоящее время есть атрибут __name__ атрибут __qualname__. Первое, что вы можете подумать; второй пунктирный "путь" для вложенных классов.

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

Теперь для вложенных классов различия между двумя атрибутами показывают:

class Outer:
    class Inner:
        pass
print(Outer.__name__, Outer.__qualname__)
print(Outer.Inner.__name__, Outer.Inner.__qualname__)

печатает:

Outer Outer
Inner Outer.Inner

Если вы хотите изменить Outer имя, вам нужно исправить три места, а именно: Outer.__name__, Outer.__qualname__, Inner.__qualname__. Для последних двух вам нужно правильно разделить и объединить точки.

Последнее предупреждение: даже если вы все сделали правильно, такие вещи, как сфинкс, пилинт и т.д., Все равно могут не работать на 100%. Например, поддельное имя не может быть найдено в пространстве имен модуля как обычно; источник не может быть grep ped для определения класса; и так далее.