如何在函数中动态生成子类?
how to dynamically generate a subclass in a function?
我正在尝试编写一个函数来创建一个新的子类,该子类以作为参数传递的字符串命名。我不知道什么工具最适合这个,但我在下面的代码中试了一下,只成功地创建了一个名为 "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)
最安全、最简单的方法是使用 type
内置函数。这需要一个可选的第二个参数(基 classes 的元组)和第三个参数(函数字典)。我的建议如下:
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)
您需要将您希望新 class 拥有的所有内容填充到第三个参数的字典中。您很可能正在生成 classes 并希望将它们推回到列表中,其中名称实际上并不重要。不过我不知道你的用例。
或者您可以访问 globals
并将新的 class 放入其中。这是生成 classes 的一种非常奇怪的动态方式,但这是我能想到的获得您似乎想要的东西的最佳方式。
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})
Ryan 的回答是完整的,但我认为值得注意的是,除了使用内置 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()
请注意,我只在创建 class Y
和初始化 Y
的实例时使用字符串,因此此方法是完全动态的。
我正在尝试编写一个函数来创建一个新的子类,该子类以作为参数传递的字符串命名。我不知道什么工具最适合这个,但我在下面的代码中试了一下,只成功地创建了一个名为 "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)
最安全、最简单的方法是使用 type
内置函数。这需要一个可选的第二个参数(基 classes 的元组)和第三个参数(函数字典)。我的建议如下:
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)
您需要将您希望新 class 拥有的所有内容填充到第三个参数的字典中。您很可能正在生成 classes 并希望将它们推回到列表中,其中名称实际上并不重要。不过我不知道你的用例。
或者您可以访问 globals
并将新的 class 放入其中。这是生成 classes 的一种非常奇怪的动态方式,但这是我能想到的获得您似乎想要的东西的最佳方式。
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})
Ryan 的回答是完整的,但我认为值得注意的是,除了使用内置 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()
请注意,我只在创建 class Y
和初始化 Y
的实例时使用字符串,因此此方法是完全动态的。