Reputation: 33
I got this code and i'm trying to figure out how this works
class Animal(object):
population = 0
def __init__(self, name):
self.name = name
def __str__(self):
return "I am an instance of {}. ".format(self.__class__, self.name)
def __repr__(self):
return self.__str__()
def make_sound(self):
return "{} is trying to speak, but its method doesn't do much".format(self.name)
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
def __str__(self):
print(super().__str__())
return "My breed is {}".format(self.breed)
def make_sound(self):
return "{} says woof!".format(self.name)
class Cat(Animal):
pass
animals = {'Felix': ('Cat', None), 'Fido': ('Dog', 'mutt'), 'Charlie': ('Dog', 'spaniel')}
animals_list = []
for k in animals:
if animals[k][1]:
animals_list.append(globals()[animals[k][0]](k, animals[k][1]))
else:
animals_list.append(globals()[animals[k][0]](k))
Animal.population+=1
for animal in animals_list:
print(animal)
print(animal.make_sound())
print("Animal population is {}".format(Animal.population))
How are the classes initiated? I can't get my head around how this is done, seems the classes dog and cat are already initiated when the script reaches the if animals part.
Thanks in advance
Upvotes: 0
Views: 135
Reputation: 94871
The classes are instantiated inside this for loop:
for k in animals:
if animals[k][1]:
animals_list.append(globals()[animals[k][0]](k, animals[k][1])) # Instantiates a class
else:
animals_list.append(globals()[animals[k][0]](k)) # Instantiates a class
So, if k
is 'Felix'
, this code is saying:
if None: # Because animals['Felix'][1] is None
animals_list.append(globals()['Cat']('Felix', None))
else:
animals_list.append(globals()['Cat']('Felix'))
globals()
returns a dictionary containing the name -> object mapping of all variables in the global namespace. So, globals()['Cat']
returns the actual Cat
class. That means globals()['Cat']('Felix')
is equivalent to Cat('Felix')
. And that, obviously, is instantiating the Cat
class with the name 'Felix'
. This same pattern repeats for every entry in the animals
dict, so in the end, the animals_list
contains the instances returned by calling Cat('Felix')
, Dog('Fido', 'mutt')
, and Dog('Charlie', 'spaniel')
.
And for what its worth, I agree with the commentors who have pointed out this code is quite ugly. It makes much more sense to do this:
animals = {'Felix': (Cat, None), 'Fido': (Dog, 'mutt'), 'Charlie': (Dog, 'spaniel')}
animals_list = []
for k in animals:
if animals[k][1]:
animals_list.append(animals[k][0](k, animals[k][1]))
else:
animals_list.append(animals[k][0](k))
No need to use globals()
.
Upvotes: 1