当前位置: 代码迷 >> python >> 在Python中动态创建类及其构造函数
  详细解决方案

在Python中动态创建类及其构造函数

热度:98   发布时间:2023-07-16 10:05:30.0

我必须创建给定类的许多子类。 我不想手动执行此操作(由于类的数量可能很大。我有一个几乎可以正常工作的解决方案...几乎-请看下面的示例,请告诉我我做错了什么。

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")

问题在于,仅当您创建循环中定义的类的实例时,才会对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的评论,在这里看到更好的解释: 。

希望能有所帮助。