在分配变量值之前使用的变量值仍然有效,这个 { k: v for k, v in ... } 语法是如何工作的?

Variable values used before they are assigned and still it works, how does this { k: v for k, v in ... } syntax work?

在下面的代码中,我无法理解变量 fieldvalue 的使用方式,因为它们是在 for 循环的下一行中分配的。

我查看了此语法和示例中的 for,但找不到任何有用的信息来解释此行为。

match = re.search(someregx, some_text)
current_row = {
    field: value.strip() if value else '' for field, value in match.groupdict().items()
}

是字典理解,相当于

current_row = {}
for field, value in match.groupdict().items():
    if value:
        current_row[field] = value.strip()
    else:
        current_row[field] = ''

这是一个dict comprehension。它根据指定的表达式创建字典。 {...} 等同于 Python 中的 dict(...) 语法。 (在这种特殊情况下,它专门从 iterable 创建一个 dict(iterable);见底部)。

好的,那么这些 Python 行话是什么意思?首先,考虑 Python 中的 list comprehension 这是一个从给定输入创建 list 的表达式,例如:

odd_numbers = [ n for n in range(100) if n%2 == 1 ] 

同理,我们先从最基本的dict理解开始:

{ k: v for k, v in ... } 

并注意 RHS match.groupdict().items() 是一个可迭代的,我们只是迭代正则表达式匹配的输出,作为字典项。 (让我们在 RHS 后面写 ...,以尽量减少混乱)。

接下来,在Python中添加v if v else ''是一个conditional expression,这里只是处理其中一个value是None的情况,并给出 empty-string '' 而不是 None (如果你试图对它做进一步的 string-processing 会(恼人地)抛出异常,并且大概我们不想写 try...except 大约每次我们尝试处理字符串时 value)。正如您所说,它会在 Python 中抛出新用户,因为条件表达式中的 if 在定义它们的可迭代对象之前。第一次看到它时,它看起来像是一堆顺序错误的关键字:) (推导式、条件表达式以及组合和嵌套这些的组合允许 Python 在紧凑的同时真正表达。)

因此我们正在寻找:

{ k: v if v else '' for k, v in ... } 

或者在这种特殊情况下,调用关键变量 field:

{ field: value.strip() if value else '' for field, value in match.groupdict().items() }

一旦您知道 {...} 等同于 dict(...)help(dict) 信息将帮助您理解 此代码正在创建一个 dict(iterable) iterable; dict(...):

语法中显示的第三种情况
class dict(object)
 |  dict() -> new empty dictionary
 |
 |  dict(mapping) -> new dictionary initialized from a mapping object's
 |      (key, value) pairs
 |
 |  dict(iterable) -> new dictionary initialized as if via:
 |      d = {}
 |      for k, v in iterable:
 |          d[k] = v
 | ...

杂项提示:

  • 格式化:不要像 C/C++/Java 复合语句块一样在单独的行上格式化大括号,Python 根本不使用那样的大括号,我们为此感到非常自豪 :)。在 Python 中 {...} 等同于 dict(...)。因此,每当您看到大括号时,您就是在查看字典、嵌套字典、dict-of-list、JSON 表达式等...
  • ... 或者 setset 本质上是一个有键但没有值的字典,例如{'b', 'f', 'g'}。你也可以有一个 set comprehension,除了 { k: v for k, v ... } 它只是 { k for k in ... }。这是一个示例:odd_numbers = { n for n in range(100) if n%2 == 1 }。在集合中,顺序无关紧要,这与元组不同。
  • 没有周围的 spaces:我在 [ ... ]{ ... } 周围用 space 写了 dict,list 和 set comprehensions,但这只是为了清楚解释语法。 Pythonic (PEP-8) 方式不是写一个 space.
  • 简洁:在字典理解中通常会给出 keyvalue 非常短或 one-letter 名称 { k: v for k, v in ... },尤其是。如果它们是复杂的表达式,那么您就不会反复浪费 space 并且需要大行或换行。
  • 相关问题:Create a dictionary with list comprehension, How to use if/else in a dictionary comprehension?
  • 也请略读 Python Programming FAQ and Functional Programming HOWTO,刚好足以让您理解概念,并在将来看到有人使用它时识别语法,然后您可以返回并阅读更多详细信息。