Учитывая ваши ограничения, каждый, кто пытается реализовать то, что вы ищете, используя dict
, лает не на то дерево. Вместо этого вы должны написать list
подкласс, который переопределяет __getitem__
, чтобы обеспечить желаемое поведение. Я написал это так, что сначала он пытается получить нужный элемент по индексу, а затем возвращается к поиску элемента по атрибуту key
содержащихся объектов. (Это может быть свойство, если объект должен определять это динамически.)
Нет способа избежать линейного поиска, если вы не хотите что-то дублировать; Я уверен, что реализация C # делает то же самое, если вы не разрешаете ей использовать словарь для хранения ключей.
class KeyedCollection(list):
def __getitem__(self, key):
if isinstance(key, int) or isinstance(key, slice):
return list.__getitem__(key)
for item in self:
if getattr(item, "key", 0) == key:
return item
raise KeyError('item with key `%s` not found' % key)
Возможно, вы также захотите переопределить __contains__
аналогичным образом, чтобы вы могли сказать if "key" in kc...
. Если вы хотите сделать его еще более похожим на dict
, вы также можете реализовать keys()
и так далее. Они будут одинаково неэффективны, но у вас будет такой API, как dict
, который также работает как список.