Python 双向映射
我不太确定该怎么称呼我正在寻找的东西;如果我在其他地方没有找到这个问题,我很抱歉。简单来说,我正在编写Python代码,直接与Linux内核进行交互。从包含的头文件中获取所需的值并将它们写入我的源代码是很简单的:
IFA_UNSPEC = 0
IFA_ADDRESS = 1
IFA_LOCAL = 2
IFA_LABEL = 3
IFA_BROADCAST = 4
IFA_ANYCAST = 5
IFA_CACHEINFO = 6
IFA_MULTICAST = 7
在构建要发送给内核的结构体时,使用这些值也很方便。然而,这些值几乎对解析内核返回的响应没有帮助。
如果我把这些值放到字典里,我想我得扫描字典中的所有值,以查找内核中每个结构体的每个项目的键。这肯定有更简单、更高效的方法。
你会怎么做呢?(如果这个问题标题不合适,随便改一下)
3 个回答
1
我最后做的是把常量值留在模块里,并创建了一个字典。这个模块是 ip_addr.py
(这些值来自 linux/if_addr.h),所以在构建要发送给内核的结构时,我可以使用 if_addr.IFA_LABEL
,并用 if_addr.values[2]
来解析响应。我希望这样做是最简单明了的,这样当我一年后再看这个时,能容易理解 :p
IFA_UNSPEC = 0
IFA_ADDRESS = 1
IFA_LOCAL = 2
IFA_LABEL = 3
IFA_BROADCAST = 4
IFA_ANYCAST = 5
IFA_CACHEINFO = 6
IFA_MULTICAST = 7
__IFA_MAX = 8
values = {
IFA_UNSPEC : 'IFA_UNSPEC',
IFA_ADDRESS : 'IFA_ADDRESS',
IFA_LOCAL : 'IFA_LOCAL',
IFA_LABEL : 'IFA_LABEL',
IFA_BROADCAST : 'IFA_BROADCAST',
IFA_ANYCAST : 'IFA_ANYCAST',
IFA_CACHEINFO : 'IFA_CACHEINFO',
IFA_MULTICAST : 'IFA_MULTICAST',
__IFA_MAX : '__IFA_MAX'
}
3
你的解决方案让重复创建文件的人工作量很大。这很容易出错(你实际上需要把每个名字写三遍)。如果你有一个文件需要不时更新(比如,当新的内核版本发布时),迟早会出现错误。其实,我只是想说,你的解决方案违反了DRY原则,也就是“不要重复自己”。
我会把你的解决方案改成这样:
IFA_UNSPEC = 0
IFA_ADDRESS = 1
IFA_LOCAL = 2
IFA_LABEL = 3
IFA_BROADCAST = 4
IFA_ANYCAST = 5
IFA_CACHEINFO = 6
IFA_MULTICAST = 7
__IFA_MAX = 8
values = {globals()[x]:x for x in dir() if x.startswith('IFA_') or x.startswith('__IFA_')}
这样生成的values
字典是自动的。你可能需要(或者必须)根据文件中的其他内容来更改if
语句中的条件。也许可以像下面这样。这个版本就不需要在if语句中列出前缀,但如果文件中有其他内容,它就会出错。
values = {globals()[x]:x for x in dir() if not x.endswith('__')}
当然,你可以在这里做得更复杂一些,比如检查是否有重复的值。
11
如果你想使用两个字典,可以试试这个方法来创建一个反转的字典:
b = {v: k for k, v in a.iteritems()}