按名称引用对象作为属性
referencing objects by name as attributes
是否有充分的理由 to/not 将对象列表存储为 "sub attributes"?在下面的示例中,我将几个动物对象存储在 animals
属性下的 Zoo 中,例如 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
在我看来,这样做会使您的代码难以调试、不灵活且不可读。这是个坏主意。 如果发生什么情况,例如:
- 你有一个包含 space 的动物名称?比如"electric eel"?
- 如果你想遍历动物,你将不得不做
for name in vars(obj):
print(getattr(obj, name))
- 本质上,您可能不得不重新实现所有标准容器功能,例如插入、添加、删除、过滤等,或者使用非常不直观的语法。
- 您将如何将其与另一个动物园合并或过滤?如果需要,也无法对这些值进行排序。
属性用于建模对象的 "hold data" 或 "describe features"。您应该仅将它们用于该目的。
由于您主要是寻求快速便捷的访问,请使用 dict
或 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
是否有充分的理由 to/not 将对象列表存储为 "sub attributes"?在下面的示例中,我将几个动物对象存储在 animals
属性下的 Zoo 中,例如 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
在我看来,这样做会使您的代码难以调试、不灵活且不可读。这是个坏主意。 如果发生什么情况,例如:
- 你有一个包含 space 的动物名称?比如"electric eel"?
- 如果你想遍历动物,你将不得不做
for name in vars(obj): print(getattr(obj, name))
- 本质上,您可能不得不重新实现所有标准容器功能,例如插入、添加、删除、过滤等,或者使用非常不直观的语法。
- 您将如何将其与另一个动物园合并或过滤?如果需要,也无法对这些值进行排序。
属性用于建模对象的 "hold data" 或 "describe features"。您应该仅将它们用于该目的。
由于您主要是寻求快速便捷的访问,请使用 dict
或 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