Есть ли в Python бесконечный словарь?

Есть ли в Python что-то вроде «бесконечного словаря»?

Точнее, есть ли что-то, куда я могу вводить значения, как в словаре, но, возможно, также есть функция, которая говорит мне, как сопоставить ключ со значением, и, возможно, также что-то, что сопоставляет ключ с (конечным) набор ключей, а затем дает соответствующее значение? Сформулировав по-другому, я хочу иметь следующую «вещь»: я инициализирую ее каким-то образом (задаю значения, функции и т. д.), а затем она просто дает мне значение для каждой клавиши (по запросу).


person Daniel Krenn    schedule 21.03.2012    source источник
comment
Итак, если я правильно понимаю, вы хотите дать словарю ключ, и он даст вам значение, которое вы не вставляли в словарь? (Вы хотите, чтобы он генерировал значение из ключа?)   -  person Corbin    schedule 22.03.2012
comment
Как вы представляете себе работу этого сочетания определенных значений и автоматически сгенерированных значений? Как решается, используется ли конкретное значение или какая функция вызывается для получения значения?   -  person Niklas B.    schedule 22.03.2012
comment
Я немного смущен тем, что именно вы хотите... почему простой словарь не подойдет? Вы вообще изучали словари Python?!   -  person Patrick T Nelson    schedule 22.03.2012
comment
Извините, не понимаю. Предполагая, что у вас есть этот бесконечный словарь, приведите пример того, как его использовать.   -  person bereal    schedule 22.03.2012
comment
То, что вам нужно, это технически (математически говоря) функция, вопрос в том, что вам нужно сделать, что вы не можете сделать (или что неудобно) с (программно говоря) функцией. Вам действительно нужен объект для выполнения этой работы?   -  person trutheality    schedule 22.03.2012
comment
Чтобы было ясно (поскольку это не из моего исходного сообщения): я знаю, как я реализовал бы это, но кто-нибудь уже сделал это? Я имею в виду, есть ли уже класс Infinite_dict, который делает все это хорошо, и мне больше не нужно думать об этой реализации?   -  person Daniel Krenn    schedule 22.03.2012


Ответы (5)


Вы захотите создать класс со специальным методом __getitem__(self,key), который возвращает соответствующее значение для этого ключа.

person Russell Borogove    schedule 21.03.2012

То, что вам нужно, называется «функцией».

Теперь, на менее саркастической ноте: я точно не знаю, чего вы пытаетесь достичь, но вот пример:

Вам нужен фрагмент кода, который возвращает n-й элемент в арифметической прогрессии. Вы можете сделать это с помощью функций:

def progression(first_element, ratio):
    def nth_element(n):
        return n*ratio + first_element
    return nth_element

my_progression = progression(2, 32)
print my_progression(17) # prints 546

Это можно расширить, если, например, вам нужна функция, сохраняющая состояние.

Надеюсь это поможет

person Gabi Purcaru    schedule 21.03.2012

Если вам нужно нормальное поведение для существующих ключей и особое поведение для несуществующих ключей, есть метод __missing__, который вызывается для отсутствующих ключей.

class funny_dict(dict):
    def __missing__(self, key):
        return "funny" * key

d = funny_dict()
d[1] = "asdf"
d[3] = 3.14
for i in range(5):
    print(i, d[i])

print(d)

Выход:

0 
1 asdf
2 funnyfunny
3 3.14
4 funnyfunnyfunnyfunny
{1: 'asdf', 3: 3.14}
person Reinstate Monica    schedule 21.03.2012

Простым способом сделать это было бы использование функционального объекта для обоих вариантов использования. Если вы хотите использовать функцию ключ-значение, вы просто используете ее непосредственно в качестве ссылки. Чтобы адаптировать обычный словарь к этому интерфейсу, вы можете обернуть его в лямбда-блок. Вот так:

# Use function as dictionary
def dict_func(key):
    return key * key
dictionary = dict_func
print dictionary(2) # prints 4

# Use normal dictionary with the same interface
normal_dict = {1: 1, 2: 4, 3: 9}
dictionary = lambda(key): normal_dict[key]
print dictionary(2) # also prints 4

# Lambda functions store references to the variables they use,
# so this works too:
def fn_dict(normal_dict):
    return lambda(key): normal_dict[key]
dictionary = fn_dict({1: 1, 2: 4, 3: 9})
print dictionary(3) # prints 9
person Denis Washington    schedule 21.03.2012

Я думаю, вы хотите что-то вроде этого, где вы dict действуете как обычный словарь, но для специальных ключей вы хотите изменить поведение, например.

class InfiniteDict(dict):
    def __init__(self, *args, **kwargs):
        self.key_funcs = kwargs.pop('key_funcs', [])
        super(InfiniteDict, self).__init__(*args, **kwargs)

    def __getitem__(self, key):
        try:
            return super(InfiniteDict, self).__getitem__(key)
        except KeyError:
            return self._get_value_from_functions(key)

    def _get_value_from_functions(self, key):
        """
        go thru list of user defined functions and return first match
        """
        for key_func in self.key_funcs:
            try:
                return key_func(key)
            except KeyError:
                pass

        raise KeyError(key)

def double_even_int(key):
    try:
        if int(key)%2 == 0:
            return int(key)*2
        else:
            raise KeyError(key)
    except ValueError:
        raise KeyError(key)

def tripple_odd_int(key):
    try:
        if int(key)%2 == 1:
            return int(key)*3
        else:
            raise KeyError(key)
    except ValueError:
        raise KeyError(key)

inf = InfiniteDict(key_funcs=[double_even_int, tripple_odd_int])
inf['a'] = 'A'

print inf['a'], inf[1], inf['2']

выход:

A 3 4
person Anurag Uniyal    schedule 21.03.2012