Я не знаю, что то, что я пытаюсь сделать, настолько не-Pythonic, что я просто пытаюсь сделать это неправильно, или если я не знаю, как спросить вопрос правильно. Для меня имеет смысл это сделать, но я искал 15 разных способов и не могу найти ответ.Доступ к списку объектов Python по атрибуту объекта
Что я хочу сделать, кажется таким простым: у меня есть список объектов. Я хочу получить доступ к этому списку с помощью свойства объектов. Этот код работает:
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
Но действительно ли мне нужно, чтобы мой собственный класс списка сделал что-то такое простое? Нет ли общего способа, кроме цикла или списка? Кажется, что это должно быть очень распространенным явлением, чтобы иметь список объектов и доступ к элементам в списке по свойствам объектов. Похоже, он должен быть обычно поддержан способом, подобным sorted(key=...)
.
Обратите внимание, что это не тот случай, когда требуется dict. В самом деле, весь смысл использования списка объектов вместо Dict, чтобы избежать того, чтобы сделать что-то вроде:
fruits = {'apple': Fruit('apple', 'red')}
... которая требует от вас ввести apple
дважды. Похоже, что там должен быть универсальный способ сделать что-то вроде этого:
print 'Apples are', fruits['apple'].color
... без подклассы list
.
И хорошо, вы можете построить Dict так:
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')])
Ну что ж, спасибо, я узнал много уже от этого вопроса.
Помимо объяснения: '{Foo, Bar, Baz} 'является * set *,' {'foo': Foo, 'bar': Bar} 'is * dict *. Обратите внимание, что у одного есть ключи, а другой нет. – deceze
Глупый я, я забыл, что '{}' также создает множества. :) – blujay