Python 如何制作一个多键对应一个值的字典?

Python 如何制作一个多键对应一个值的字典?,python,dictionary,Python,Dictionary,我有一个关于我想编一本字典的问题。我的目标是为单个值设置多个键,如下所示: dictionary = {('a', 'b'): 1, ('c', 'd'): 2} assert dictionary['a'] == 1 assert dictionary['b'] == 1 有什么想法吗?我想你的意思是: class Value: def __init__(self, v=None): self.v = v v1 = Value(1) v2 = Value(2) d

我有一个关于我想编一本字典的问题。我的目标是为单个值设置多个键,如下所示:

dictionary = {('a', 'b'): 1, ('c', 'd'): 2}
assert dictionary['a'] == 1
assert dictionary['b'] == 1
有什么想法吗?

我想你的意思是:

class Value:
    def __init__(self, v=None):
        self.v = v

v1 = Value(1)
v2 = Value(2)

d = {'a': v1, 'b': v1, 'c': v2, 'd': v2}
d['a'].v += 1

d['b'].v == 2 # True
  • Python的字符串和数字是不可变的对象
  • 因此,如果希望
    d['a']
    d['b']
    指向在其更改时“更新”的相同值,请使该值引用一个可变对象(如上所述的用户定义类,或
    dict
    列表
    设置
  • 然后,当您在
    d['a']
    修改对象时,
    d['b']
    会同时更改,因为它们都指向同一个对象

如果使用
fromkeys
,您的示例将创建多个key:value对。如果不希望这样,可以使用一个密钥并为该密钥创建别名。例如,如果您使用的是寄存器映射,则密钥可以是寄存器地址,别名可以是寄存器名称。这样,您就可以在正确的寄存器上执行读/写操作

>>> mydict = {}
>>> mydict[(1,2)] = [30, 20]
>>> alias1 = (1,2)
>>> print mydict[alias1]
[30, 20]
>>> mydict[(1,3)] = [30, 30]
>>> print mydict
{(1, 2): [30, 20], (1, 3): [30, 30]}
>>> alias1 in mydict
True

如果你要经常添加到这本词典中,你会想采用基于类的方法,类似于@Latty在这个问题中的回答

但是,如果您有一个静态字典,并且您只需要通过多个键访问值,那么您可以使用两个字典这一非常简单的方法。一个用于存储别名密钥关联,另一个用于存储实际数据:

alias = {
    'a': 'id1',
    'b': 'id1',
    'c': 'id2',
    'd': 'id2'
}

dictionary = {
    'id1': 1,
    'id2': 2
}

dictionary[alias['a']]
如果需要添加到字典中,可以编写这样的函数来使用这两个字典:

def add(key, id, value=None)
    if id in dictionary:
        if key in alias:
            # Do nothing
            pass
        else:
            alias[key] = id
    else:
        dictionary[id] = value
        alias[key] = id

add('e', 'id2')
add('f', 'id3', 3)

虽然这是可行的,但我认为最终如果您想做类似的事情,编写您自己的数据结构可能是一种方法,尽管它可以使用类似的结构。

这很简单。首先要了解Python解释器的设计。它基本上不会为所有变量分配内存,如果任何两个或更多变量具有相同的值,它只会映射到该值

让我们转到代码示例

In [6]: a = 10

In [7]: id(a)
Out[7]: 10914656

In [8]: b = 10

In [9]: id(b)
Out[9]: 10914656

In [10]: c = 11

In [11]: id(c)
Out[11]: 10914688

In [12]: d = 21

In [13]: id(d)
Out[13]: 10915008

In [14]: e = 11

In [15]: id(e)
Out[15]: 10914688

In [16]: e = 21

In [17]: id(e)
Out[17]: 10915008

In [18]: e is d
Out[18]: True
In [19]: e = 30

In [20]: id(e)
Out[20]: 10915296
从上面的输出来看,变量a和b共享相同的内存,当我创建一个新变量e并存储一个值(11)时,c和d具有不同的内存它已经存在于变量c中,因此它映射到该内存位置,当我将变量e中的值更改为变量d中已经存在的21时,它不会创建新内存,因此现在变量d和e共享相同的内存位置。最后,我将变量e中的值更改为30,该值不存储在任何其他变量中,因此它为e创建了一个新内存

因此,任何具有相同值的变量都共享内存

不适用于列表和字典对象

让我们来回答你的问题

当多个键具有相同的值时,所有键都共享相同的内存,因此您所期望的东西已经存在于python中

你可以这样简单地使用它

In [49]: dictionary = {
    ...:     'k1':1,
    ...:     'k2':1,
    ...:     'k3':2,
    ...:     'k4':2}
    ...:     
    ...:     

In [50]: id(dictionary['k1'])
Out[50]: 10914368

In [51]: id(dictionary['k2'])
Out[51]: 10914368

In [52]: id(dictionary['k3'])
Out[52]: 10914400

In [53]: id(dictionary['k4'])
Out[53]: 10914400

根据上述输出,键k1和k2映射到同一地址,这意味着值1仅在内存中存储一次,即多键单值字典。这是您想要的:P

短版和中间版

具有多个键

#!/usr/bin/env python3

def get_keys(s):
    # Lower the user's entry to easily manipulate data
    s = s.lower()
    
    # Create a list to simulate multiple keys
    numbers = ['uno', 'one', 'um', 'eins', 'ein']
    
    # Lambda for input validation
    validator = lambda x: x if x in numbers else 'no-key-found'  # return me x if x is found in the list numbers, contratiwise return me 'no-key-found'
    
    dic = {
        validator(s):'1',
        'no-key-found':'Key does not exist'
    }
    
    
    return dic[validator(s)]


print(get_keys(input('Type in word: ')))
更简单的版本


@邪恶在里面,啊,如果这是你想要的,为什么你不给两把钥匙都分配1呢?它可能是有用的@Eli的可能副本,而不是副本。事实上,链接是这个的复制品。查看帖子的时间。您不必使用不可变对象,只需使用相同的变量(引用对象)赋值,就可以得到可变和不可变对象的相同结果,例如
num=2
,而不是直接使用对象(
num
是变量,
2
是对象)。您可以使用
is
关键字来测试它,例如:
如果d['a']是d['b']:
。如果两个键都指向同一个对象,则表达式将为
True
@Yomi这不适用于分配新的(不可变的)对象!它们最初可能指向同一个对象(使用整数,即使将文字值放在那里)。但是尝试将
d['a']
的值重新指定给不同的整数变量,并确保
d['b']
不会更改。无论是使用变量名还是文字编号,这都无关紧要,因为它只为一个字典条目而不是另一个条目分配一个新的(不可变的)对象。它不知道哪个键与value具有相同的对象,哪个键也应该更改为指向另一个对象。我认为这只是因为Python存储的对象数量较小,所以不必每次都重新创建它们。如果要存储更复杂的数据,例如更大的数字或字符串等,则情况并非如此。
#!/usr/bin/env python3

import sys


def week_days():
    # Assets
    number_day = ['1', '2', '3', '4', '5', '6', '7']
    
    # Introduction
    print('Welcome to the Week Day Finder')
    
    # User input
    day = input('Please, enter the day you want to check: ').lower()
    WEEK_COLOR = {'RED': '\u001b[31m', 'GREEN': '\u001b[32m'}
    
    # Day validator
    days = {
        '1' if day in number_day else 'sunday': 'Weekend Day',
        '2' if day in number_day else 'monday': 'Week Day',
        '3' if day in number_day else 'tuesday': 'Week Day',
        '4' if day in number_day else 'wednesday': 'Week Day',
        '5' if day in number_day else 'thursday': 'Week Day',
        '6' if day in number_day else 'friday': 'Week Day',
        '7' if day in number_day else 'saturday': 'Weekend Day'
    }
    
    # Logical trial
    try:
        if days[day] == 'Week Day':
            print(WEEK_COLOR['GREEN'], days[day])
            
        elif days[day] == 'Weekend Day':
            print(WEEK_COLOR['RED'], days[day])
            
    except KeyError:
        print('** Invalid Day **', file=sys.stderr)
        
        
def main():
    week_days()
    
    
if __name__ == '__main__':
    main()