可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is there something like an "infinite dictionary" in Python?
More precisely, is there something where
- i can put in values like in a dictionary,
- but maybe also a function which tells me how to map a key to a value,
- and maybe also something that maps a key to a (finite) set of keys and then gives the corresponding value?
Formulated in another way, what I want to have is the following "thing":
I initialize it in a way (give values, functions, whatever) and then it just gives me for each key a value (on request).
回答1:
What you need is called a "function".
Now, on a less sarcastic note: I don't know exactly what you are trying to achieve, but here's an example:
You want a piece of code that returns the nth element in an arithmetic progression. You can do it this way with functions:
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
This can be extended if, for example, you need a function that retains state.
Hope this helps
回答2:
You will want to create a class with the special method __getitem__(self,key)
that returns the appropriate value for that key.
回答3:
If you want normal behaviour for existing keys, and special behavior for non-existing keys, there's the __missing__
method that's called for missing keys.
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)
Output:
0
1 asdf
2 funnyfunny
3 3.14
4 funnyfunnyfunnyfunny
{1: 'asdf', 3: 3.14}
回答4:
An easy way to do this would be to use a function object for both use cases. If you want to use a key-value function, you just just use it directly as a reference. To adapt an ordinary dictionary to this interface, you can wrap it in a lambda block. Like so:
# 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
回答5:
I think you want something like this, where you dict
act like a normal dictionary but for special keys you want to change the behavior e.g.
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']
output:
A 3 4