The problem is that i
variable inside the lambda
is evaluated only when you create an instance of the class you've defined in a loop. At this time the loop would finish and i
would be set to the last item in the list - Parrot
.
You should pass i
to the lambda:
ZOO_CLASSES[i] = type(i,
(Animal,),
dict(__init__=lambda self, i=i: Animal.__init__(self, i)))
^
Demo:
>>> 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'
Also, thanks to @BrenBarn's comment, see a better explanation here: Python lambda closure scoping.
Hope that helps.