问题描述
我必须创建给定类的许多子类。 我不想手动执行此操作(由于类的数量可能很大。我有一个几乎可以正常工作的解决方案...几乎-请看下面的示例,请告诉我我做错了什么。
ZOO_CLASSES字典为我们创建的类的每个动物(字符串)保存(并且必须保存)。
最终解决方案必须使用动物基类的继承,并且每个动物物种的对象都必须使用
one_lion = Lion()
要么
one_lion = ZOO_CLASSES['Lion']()
我发现的问题是(如测试将显示是否运行它们-而不是“真实,错误,这是狮子,这是熊”,而是“真实,正确,这是鹦鹉,这是鹦鹉”。我认为问题在于,在调用构造函数并评估其参数(自身和i)时,它会获取其最后分配的值(i =“ Parrot”)。但是,我创建的对象具有正确的类类型,而我却没有看到任何其他意外行为。
顺便说一下,我是Python的新手。 :)
class Animal:
def __init__(self, name):
self.name = name
def __str__(self):
return "This is " + self.name
def __eq__(self, other):
return self.name == other.name
ZOO = ['Lion', 'Bear', 'Parrot'] # list with many animals
ZOO_CLASSES = {}
for i in ZOO:
ZOO_CLASSES[i] = type(i, (Animal,), dict(__init__=lambda self: Animal.__init__(self, i)))
# or even tried:
for i in ZOO:
def constructor(self):
Animal.__init__(self, i)
ZOO_CLASSES[i] = type(i, (Animal,), dict(__init__=constructor))
# each time it creates a different function (as should be) but the value of i stays to the last one in the list:
# tests:
print(ZOO_CLASSES["Lion"]() == ZOO_CLASSES["Lion"]()) # True
print(ZOO_CLASSES["Lion"]() == ZOO_CLASSES["Bear"]()) # False
print(str(ZOO_CLASSES["Lion"]())) # This is Lion
print(str(ZOO_CLASSES["Bear"]())) # This is Bear
# i.e. all times we call these classes (their constructors) - i gets evaluated as "Parrot" (last element of ZOO list)
###################
# I don't want to do this (because imagine if the list ZOO is really long,
# manually typing it would be stupid):
class Lion(Animal):
def __init__(self):
Animal.__init__(self, "Lion")
class Bear(Animal):
def __init__(self):
Animal.__init__(self, "Bear")
class Parrot(Animal):
def __init__(self):
Animal.__init__(self, "Parrot")
1楼
问题在于,仅当您创建循环中定义的类的实例时,才会对lambda
中的i
变量进行求值。
此时,循环将结束, i
将被设置为列表中的最后一项- Parrot
。
您应该将i
传递给lambda:
ZOO_CLASSES[i] = type(i,
(Animal,),
dict(__init__=lambda self, i=i: Animal.__init__(self, i)))
^
演示:
>>> class Animal:
... def __init__(self, name):
... self.name = name
...
>>> ZOO = ['Lion', 'Bear', 'Parrot']
>>> ZOO_CLASSES = {}
>>> for i in ZOO:
... ZOO_CLASSES[i] = type(i, (Animal,), dict(__init__=lambda self: Animal.__init__(self, i)))
...
>>> i
'Parrot'
>>> ZOO_CLASSES["Lion"]().name
'Parrot'
>>> for i in ZOO:
... ZOO_CLASSES[i] = type(i, (Animal,), dict(__init__=lambda self, i=i: Animal.__init__(self, i)))
...
>>> ZOO_CLASSES["Lion"]().name
'Lion'
另外,感谢@BrenBarn的评论,在这里看到更好的解释: 。
希望能有所帮助。