【问题标题】:Python dictionary comprehensionPython 字典理解
【发布时间】:2015-06-23 20:58:56
【问题描述】:

我有一个输入字典,我想将键与另一个字典进行比较,如果查找字典中的键被命中,我希望它运行一个函数作为查找字典中的值。

查找字典中的函数将返回一个需要“更新”到新字典中的键值对。所以这里是一个例子:

out = {getattr(self,self.LOOKUPDICT[k])({k:query[k]}) for k in query.keys() if k not in self.exclusions}

结果

getattr(self,self.LOOKUPDICT[k])({k:query[k]}) 

是一个看起来像这样的字典:

{'new_key':'new_val'}

在理解中我得到了

TypeError: unhashable type: 'dict'

因为它需要一个键值对。

现在我可以只运行一个常规循环和一个 if 语句,但我对这些有点反感。这里有什么解决方法吗?

TLDR: 字典推导,如何插入这样的字典:

{{'k':'v'} for k in blahblah}

并将 k 设为键,将 v 设为值。请注意,dict 是从在表达式中运行的函数返回的。

【问题讨论】:

  • 你有一个set理解;你只有一个表达式,没有键值对。什么表达式产生键,什么产生值?

标签: python-3.x dictionary dictionary-comprehension


【解决方案1】:

字典理解需要单独的 keyvalue 表达式:

{key_expr: value_expr for iterable [more if and for parts]}

但如果你的函数同时产生两者,你最好使用带有循环的 dict() 函数:

out = dict(getattr(self, self.LOOKUPDICT[k])({k: query[k]})
           for k in query if k not in self.exclusions)

因为该函数采用一系列 元组,每个元组都包含一个键值对。

注意这里不需要.keys() 调用;直接在query 上迭代就足以产生密钥。您可以在此处使用设置的交叉点; dict.keys() 对象是一个dictionary view它本身就是一个集合

out = dict(getattr(self, self.LOOKUPDICT[k])({k: query[k]})
           for k in query.keys() - self.exclusions)

query.keys() - self.exclusions 表达式生成一组位于 query 中但不在可迭代(集合、字典、列表、元组等)self.exclusions 中的键。

如果 self.LOOKUPDICT 值映射到 self 上的属性,则直接访问实例字典可能很有用:

attrs = vars(self)
out = dict(attrs[self.LOOKUPDICT[k]]({k: query[k]})
           for k in query.keys() - self.exclusions)

【讨论】:

  • 我同意 .keys() 几乎从不需要,但有时它有助于“显式胜于隐式”。
  • @PeteCacioppi:它会创建一个您不需要的额外对象,因此 Python 样式指南(以及 Google 样式指南)建议不要使用它。
  • @PeteCacioppi:在 Python 2 中,它创建了一个包含所有键的新列表对象,当仅用于迭代时就更加矫枉过正了。
  • @PeteCacioppi:最后但并非最不重要的dict类型文档explicitly documents iter(d)
  • 是的,是的,是的。但风格指南也说“我只是一个指南”。我们不是在谈论滥用 self 和 underscore 约定,而是在权衡不必要的计算时间和预期受众的可读性。
【解决方案2】:

这个怎么样

out = {_k:_v for k in query.keys() for _k,_v in getattr(self,self.LOOKUPDICT[k])({k:query[k]}).items() if k not in self.exclusions}

虽然这可能是你所追求的更多

out = {_k:_v for k in set(query.keys()).difference(self.exclusions) for _k,_v in getattr(self,self.LOOKUPDICT[k])({k:query[k]}).items()}

第二个更好,因为它不会为 getattr(self,self.LOOKUPDICT[k])({k:query[k]}) 调用 exclusions

【讨论】:

    猜你喜欢
    • 2013-01-08
    • 2022-11-22
    • 1970-01-01
    • 2013-07-28
    • 2011-06-06
    • 2018-12-22
    • 2020-10-19
    相关资源
    最近更新 更多