按名称作为属性引用对象

3

是否有好的理由来存储对象列表作为“子属性”?在下面的示例中,我将几个动物对象存储在一个动物园中的animals属性下,例如zoo.animals.<animal object referenced by name>。这种语法使得访问存储的动物的属性更容易,我想知道这种结构的缺点是否还没有被考虑到:

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

这实际上是我们工作场所标准的一部分,我不能确定它是好还是坏的做法,但我可以说的是,如果您计划添加更多的“子属性”,例如,您有一种特定类型的鸟,想要存储其爪子大小,那么这将在num_legs下进行抽象并扩展。因此,您将拥有zoo.animals.bird.num_legs.talon_size,这可能会变得非常混乱,我确实看到了很多这样的情况,但是如果您不打算很快添加到其中,我从未见过任何问题。 - GKE
这只是不必要的,也没有太大帮助。 - jamylak
1个回答

2

在我看来,这样做会让你的代码难以调试、缺乏灵活性和难以阅读,这是一个不好的想法。 例如,如果发生以下情况会怎样:

  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.

属性旨在“保存数据”或“描述建模对象的特征”。您应该仅出于这个目的使用它们。


如果您主要寻求快速和简便的访问,请使用 dictOrderedDict

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接