按对象属性访问Python对象列表
我不知道我想做的是不是太不符合python,我只是想做错事,或者我不知道如何正确地问这个问题。这对我来说是有道理的,但我已经找到了15种不同的方法,却找不到答案 我想做的事情似乎很简单:我有一个对象列表。我想通过对象的属性访问该列表。此代码适用于:按对象属性访问Python对象列表,python,Python,我不知道我想做的是不是太不符合python,我只是想做错事,或者我不知道如何正确地问这个问题。这对我来说是有道理的,但我已经找到了15种不同的方法,却找不到答案 我想做的事情似乎很简单:我有一个对象列表。我想通过对象的属性访问该列表。此代码适用于: class Fruit: def __init__(self, name, color): self.name = name self.color = color def __str__(self):
class Fruit:
def __init__(self, name, color):
self.name = name
self.color = color
def __str__(self):
return self.name
class BaseballPlayer:
def __init__(self, name, number, position):
self.name = name
self.number = number
self.position = position
def __str__(self):
return self.name
class ListByProperty(list):
def __init__(self, property, list):
super(ListByProperty, self).__init__(list)
self.property = property
def __getitem__(self, key):
return [item for item in self if getattr(item, self.property) == key][0]
fruits = ListByProperty('name', [Fruit('apple', 'red'), Fruit('banana', 'yellow')])
baseballTeam = ListByProperty('position', [BaseballPlayer('Greg Maddux', 31, 'P'),
BaseballPlayer('Javy Lopez', 8, 'C')])
teamByNumber = ListByProperty('number', baseballTeam)
print 'Apples are', fruits['apple'].color
pitcher = baseballTeam['P']
print 'The pitcher is #%s, %s' % (pitcher.number, pitcher)
print '#8 is', teamByNumber[8]
>>> Apples are red
The pitcher is #31, Greg Maddux
#8 is Javy Lopez
但是,我真的需要创建自己的列表类来做这么简单的事情吗?除了循环或listcomp之外,没有通用的方法吗?这似乎应该是一件非常常见的事情,拥有一个对象列表,并通过对象的属性访问列表中的项。它似乎应该以类似于sorted(key=…)
的方式得到普遍支持
请注意,这与需要dict的情况不同。事实上,使用对象列表而不是dict的全部目的是避免执行以下操作:
fruits = {'apple': Fruit('apple', 'red')}
…这要求您键入apple
两次。似乎应该有一种通用的方法来做这样的事情:
print 'Apples are', fruits['apple'].color
fruits = [Fruit('apple', 'red'), Fruit('banana', 'yellow')]
fruits = {f.name: f for f in fruits}
…无需子类化列表
好的,你可以建立这样一个dict:
print 'Apples are', fruits['apple'].color
fruits = [Fruit('apple', 'red'), Fruit('banana', 'yellow')]
fruits = {f.name: f for f in fruits}
或者你可以只写一行,但这仍然看起来……呃……语法上是酸的?:)
到目前为止,我认为最好的办法是:
class DictByProperty(dict):
def __init__(self, property, list):
super(DictByProperty, self).__init__({getattr(i, property): i for i in list})
self.property = property
fruits = DictByProperty('name', [Fruit('apple', 'red')])
哦,谢谢,我已经从这个问题中学到了很多
class Fruit:
def __init__(self, name, color):
self.name = name
self.color = color
fruits = dict(zip(['apple', 'banana'], [Fruit('apple', 'red'), Fruit('banana', 'yellow')]))
print("An apple is %s" % fruits['apple'].color)
或:
以下事实并不产生一个集合:
fruits = {Fruit('apple', 'red'), Fruit('banana', 'yellow')}
请注意与我创建dict的方式不同
fruits = [Fruit('apple', 'red'), Fruit('banana', 'yellow')]
print("An apple is %s" % fruits[fruits.index('apple')].color)
不起作用,因为您的列表包含类型为fruit而不是String的对象,这里的情况也一样:
fruits = FruitList([Fruit('apple', 'red'), Fruit('banana', 'yellow')])
print("An apple is %s" % fruits['apple'].color)
要使上述方法起作用,请执行以下操作:
class Fruit:
def __init__(self, name, color):
self.name = name
self.color = color
def __eq__(self, other):
if isinstance(other, Fruit):
return (self.name, self.color) == (other.name, other.color)
return self.name == other
fruits = [Fruit('apple', 'red'), Fruit('banana', 'yellow')]
print("An apple is %s" % fruits[fruits.index('apple')].color)
我不建议这样做,因为如果列表恰好包含字符串
apple
,那么对color
的属性调用将无效,因为字符串没有名为color
的属性,您可以创建一个实例
apple = Fruit('apple', 'red')
print(apple.color) # I use Python 3.x
我不确定我是否明白你的问题。但也许这有帮助
编辑:为了重新赢得我的声誉
您可以使用字典中的实例。例如
banana = Fruit('banana', 'yellow')
apple = Fruit('apple', 'red')
fruits = {'apple':apple, 'banana':banana}
或者,如果您愿意:
fruits = {'apple':Fruit('apple', 'red'), 'banana':Fruit('banana', 'yellow')}
无论哪种方式,你都可以简单地用
print(fruits['banana'].color)
除了解释:
{Foo,Bar,Baz}
是一个集合,{'Foo':Foo,'Bar':Bar}
是一个指令。请注意,一个有键,另一个没有。傻我,我忘了{/code>也有集合非常酷,stack exchange知道水果类的颜色!我不明白这为什么会被否决。这个方法有什么问题吗?我重写了我的问题,以澄清我在寻找什么,这是为了避免必须键入两次水果名称。谢谢。:)@blujay类是否绝对需要有name属性?您可以创建一个只需要颜色的类。。。e、 g fruits={'apple':Fruit('red'),等等)称为fruits['apple'].color。至少这样可以避免键入“apple”两次,并且只需要三行代码来编写类。那么,它不再是一个真正的“Fruit”类,而是一个“color”如果对象是作为参数传递的,那么它不会嵌入其水果类型,因此必须手动随它一起传递。此时,您最好只执行fruits={'apple':'red','banana':'yellow'}
。这不仅是一个冗余问题,而且是以一种似乎有意义的方式将对象保持在一起的问题。“不起作用,因为您的列表包含类型为fruit而不是string的对象…”但我设置了
在水果
对象上。我的问题是为什么索引
方法在那里不起作用。谢谢。\uuuuuuu stru\uuuuuu
方法只在打印对象时调用。它不用于比较。如果你重载了\uuuuuuu eq\uuu
方法,那么这可能会起作用。请参阅我的editAh,__eq_uu
。我不知道为什么我错过了用于列表的那个。我误解了,认为它是在dicts中使用的。谢谢。似乎这仍然是获得水果['apple'的唯一方法
工作就是对列表进行子类化。这真的是唯一的方法吗?@blujay:只使用dict。列表不是为这样使用而设计的;dict是。通过正确构建dict,可以消除使用dict时的冗长,如{x.name:x代表x in…}
example。您甚至可以编写一个helper函数来为您构建dict,因此它看起来类似于attrlookupdict(l,'name'))
。谢谢。我提出了一个使用dict的DictByProperty
类,按照您建议的方式构建它。我觉得必须有一种通用的方法或标准库来实现这一点,我只是错过了。。。