2015-03-28 1 views
1

Я пытаюсь написать функцию, которая создает новый подкласс с именем, который передается в качестве аргумента. Я не знаю, какие инструменты были бы лучше для этого, но я сделал это в коде ниже, и мне удалось создать подкласс «x», а не «MySubClass», как предполагалось. Как я могу правильно написать эту функцию?Как динамически генерировать подкласс в функции?

class MySuperClass: 
    def __init__(self,attribute1): 
     self.attribute1 = attribute1 

def makeNewClass(x): 
    class x(MySuperClass): 
     def __init__(self,attribute1,attribute2): 
      self.attribute2 = attribute2 

x = "MySubClass" 
makeNewClass(x) 
myInstance = MySubClass(1,2) 
+3

Используйте встроенную функцию 'type'. Это динамическая форма выражения класса. https://docs.python.org/2/library/functions.html#type Вы можете передать имя строки в качестве первого параметра, базовые классы в качестве второго параметра, а пространство имен - как третий параметр. – Shashank

+1

Вы должны использовать Python [metaclasses] (http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python) –

ответ

1

Самый безопасный и простой способ сделать это было бы использовать встроенную функцию type. Это принимает необязательный второй аргумент (кортеж базовых классов) и третий аргумент (dict of functions). Моя рекомендация будет следующее:

def makeNewClass(x): 
    def init(self,attribute1,attribute2): 
     # make sure you call the base class constructor here 
     self.attribute2 = attribute2 

    # make a new type and return it 
    return type(x, (MySuperClass,), {'__init__': init}) 

x = "MySubClass" 
MySubClass = makeNewClass(x) 

Вам нужно будет заполнить Dict третьего аргумента все, что вы хотите, чтобы новый класс иметь. Очень вероятно, что вы генерируете классы и захотите отбросить их обратно в список, где имена фактически не будут иметь значения. Однако я не знаю вашего случая использования.


В качестве альтернативы вы можете получить доступ к globals и поставить новый класс в том, что вместо этого. Это действительно странно динамический способ генерации классов, но это лучший способ, который я могу представить, чтобы получить именно то, что вам кажется нужным.

def makeNewClass(x): 
    def init(self,attribute1,attribute2): 
     # make sure you call the base class constructor here 
     self.attribute2 = attribute2 

    globals()[x] = type(x, (MySuperClass,), {'__init__': init}) 
+0

Сначала я сделал некоторые синтаксические ошибки, но как только я их отсортировал, ваш код работал. благодаря! – user3150635

0

ответ Райана является полным, но я думаю, что стоит отметить, что есть по крайней мере один другой гнусный способ сделать это, помимо использования встроенной type и exec/eval или что-то:

class X: 
    attr1 = 'some attribute' 

    def __init__(self): 
     print 'within constructor' 

    def another_method(self): 
     print 'hey, im another method' 

# black magics 
X.__name__ = 'Y' 
locals()['Y'] = X 
del X 

# using our class 
y = locals()['Y']() 
print y.attr1 
y.another_method() 

Обратите внимание, что я использовал строки только при создании класса Y и при инициализации экземпляра Y, поэтому этот метод является полностью динамическим.

+0

Я все еще пытаюсь выяснить, что именно это делает. Я понимаю все, кроме частей с locals(). Не возвращает ли locals() словарь локальных переменных в данной функции? и какие обозначения вы используете с locals() ['y']()? Это похоже на ссылку на элемент списка между двумя вызовами функций. объясните, поэтому я могу понять черную магию тоже. – user3150635

+0

@ user3150635 Часть ['Y'] не используется для ссылки на список. Списки в Python могут иметь только целые индексы. С другой стороны, словари могут принимать целые числа, строки и все остальное, что правильно реализует хеширующий интерфейс в качестве допустимых ключей. Вы правы, locals() возвращает словарь, затем я беру этот словарь и получаю доступ к значению для ключа «Y», который мы ранее задали в более ранней строке как значение нашего класса Y. Наконец, я создаю экземпляр класса с окончательный набор круглых скобок. – Shashank

Смежные вопросы