Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

referencing objects by name as attributes [closed]

Are there good reasons to/not to store a list of objects as "sub attributes"? In the example below, I store several animal objects in a Zoo under the animals attribute, e.g. zoo.animals.<animal object referenced by name>. This syntax makes it easier to access the attributes of the stored animals and I'm wondering if there are downsides of this construction I haven't yet considered:

class Animal(object):
    def __init__(self, name, num_legs, furry):
        self.name = name
        self.num_legs = num_legs
        self.furry = furry

class ObjAsAttributes(object):
    def __init__(self, **kwargs):
        for k,v in kwargs.items():
            setattr(self, k, v)

class Zoo(object):
    def __init__(self, animals):
        self.name = 'my zoo'
        self.hours = '8am-6pm'
        animals = {animal.name:animal for animal in animals}
        self.animals = ObjAsAttributes(**animals)




animal_list = [Animal(name='bird', num_legs=2, furry=False),
               Animal(name='giraffe', num_legs=4, furry=True),
               Animal(name='octopus', num_legs=8, furry=False)]

zoo = Zoo(animal_list)
zoo.animals.bird.num_legs
# returns 2
like image 506
anon01 Avatar asked Mar 27 '26 06:03

anon01


1 Answers

In my opinion, doing so will make your code hard to debug, inflexible and unreadable. This is a bad idea. What happens if, for example:

  1. You have a animal name that contains a space? Such as "electric eel"?
  2. If you want to iterate over animals, you will have to do
    for name in vars(obj):
        print(getattr(obj, name))
    
    • In essence, you may have to re-implement all standard container functions, such as insert, add, delete, filter, etc., or use very non-intuitive syntax.
  3. How will you merge or filter this with another zoo? Also there is no way to sort these values if you need to do so.

Attributes are meant to "hold data" or "describe features" of a modeled object. You should use them only for that purpose.


As you are mainly looking for fast and easy access, use a dict or OrderedDict:

class Animal(object):
    def __init__(self, name, num_legs, furry):
        self.name = name
        self.num_legs = num_legs
        self.furry = furry

class Zoo(object):
    def __init__(self, animals):
        self.name = 'my zoo'
        self.hours = '8am-6pm'
        self.animals = {animal.name:animal for animal in animals}

animal_list = [Animal(name='bird', num_legs=2, furry=False),
               Animal(name='giraffe', num_legs=4, furry=True),
               Animal(name='octopus', num_legs=8, furry=False)]

zoo = Zoo(animal_list)
zoo.animals['bird'].num_legs
# returns 2
like image 121
crazyGamer Avatar answered Mar 29 '26 20:03

crazyGamer