Python: класс factory с использованием ввода пользователем в качестве имен классов
Я хочу добавить класс atttributes к суперклассу динамически. Кроме того, я хочу создавать классы, которые наследуют от этого суперкласса динамически, и имя этих подклассов должно зависеть от ввода пользователем.
Существует суперкласс "Unit", к которому я могу добавлять атрибуты во время выполнения. Это уже работает.
def add_attr (cls, name, value):
setattr(cls, name, value)
class Unit(object):
pass
class Archer(Unit):
pass
myArcher = Archer()
add_attr(Unit, 'strength', 5)
print "Strenght ofmyarcher: " + str(myArcher.strength)
Unit.strength = 2
print "Strenght ofmyarcher: " + str(myArcher.strength)
Это приводит к желаемому результату:
Степень могущества: 5
Степень защиты: 2
Но теперь я не хочу предопределять подкласс Archer, но я бы предпочел, чтобы пользователь решил, как назвать этот подкласс. Я пробовал что-то вроде этого:
class Meta(type, subclassname):
def __new__(cls, subclassname, bases, dct):
return type.__new__(cls, subclassname, Unit, dct)
factory = Meta()
factory.__new__("Soldier")
но не повезло. Наверное, я не совсем понял, что здесь делает новый.
В результате я хочу, чтобы
class Soldier(Unit):
pass
создается factory. И если я вызову factory с аргументом "Рыцарь", я бы хотел создать класс Knight, подкласс Unit.
Любые идеи? Большое спасибо заранее!
Bye
-Sano
Ответы
Ответ 1
Чтобы создать класс из имени, используйте оператор class
и назначьте имя. Обратите внимание:
def meta(name):
class cls(Unit):
pass
cls.__name__ = name
return cls
Теперь, полагаю, я должен объяснить себя и так далее. Когда вы создаете класс с помощью оператора класса, он выполняется динамически - это эквивалентно вызову type()
.
Например, следующие два фрагмента делают одно и то же:
class X(object): pass
X = type("X", (object,), {})
Имя класса - первый аргумент type-- присваивается __name__
, и что в основном его конец (единственный раз __name__
используется, вероятно, в реализации по умолчанию __repr__()
). Чтобы создать класс с динамическим именем, вы можете на самом деле вызвать тип типа так, или вы можете просто изменить имя класса после этого. Синтаксис class
существует по какой-то причине, хотя... он удобен, и его легко добавить и изменить позже. Если вы хотите добавить методы, например, это будет
class X(object):
def foo(self): print "foo"
def foo(self): print "foo"
X = type("X", (object,), {'foo':foo})
и т.д. Поэтому я бы посоветовал использовать инструкцию класса - если бы вы знали, что можете сделать это с самого начала, вы, вероятно, сделали бы это. Работа с type
и т.д. - это беспорядок.
(Вы не должны, между прочим, звонить type.__new__()
вручную, только type()
)
Ответ 2
Посмотрите type()
встроенную функцию.
knight_class = type('Knight', (Unit,), {})
- Первый параметр: имя нового класса
- Второй параметр: кортеж родительских классов
- Третий параметр: словарь атрибутов класса.
Но в вашем случае, если подклассы не реализуют другое поведение, возможно, достаточно указать атрибут Unit
a name
.