Skip to content

循环与推导

字符串会切了,用循环处理一堆条目。推导式是 Python 里最常用的「map + filter」。

for / continue / enumerate / range

python
for e in feed.entries:
    if not e.get("title"):
        continue
    entries.append({...})

for idx, item in enumerate(raw_items, start=1):
    ...

for _ in range(max_retries + 1):
    try:
        ...
    except Exception:
        ...
js
for (const e of feed.entries) {
  if (!e.title) continue
  entries.push({...})
}

rawItems.forEach((item, i) => {
  const idx = i + 1
})

for (let i = 0; i < maxRetries + 1; i++) {
  try {
    // ...
  } catch (e) {}
}
PythonJavaScript
for x in list:for (const x of list)
enumerate(arr, start=1).entries() / forEachidx = i + 1
range(n)for (let i = 0; i < n; i++)
_占位,表示不用这个值

列表推导 ≈ map + filter

形式:[表达式 for 变量 in 可迭代 if 条件]

python
all_titles = [e["title"] for e in entries]
filtered = [e for e in entries if e["title"] in keep_titles]
id_set = {item.item_id for item in items}  # 集合推导,外面是 {}
js
const allTitles = entries.map((e) => e.title)
const filtered = entries.filter((e) => keepTitles.has(e.title))
const idSet = new Set(items.map((item) => item.item_id))

等价展开:

python
all_titles = []
for e in entries:
    all_titles.append(e["title"])
目的PythonJavaScript
只要副作用for e in entries:entries.forEach(...)
得到新列表[e["title"] for e in entries]entries.map(...)
过滤新列表[e for e in entries if ...]entries.filter(...)

也能写 list(map(lambda e: e["title"], entries)),但推导式更常见。map 在 Python 3 是惰性的,要包 list(...)

join 接推导

python
all_text = "\n".join(
    f"标题:{e.title}"
    for e in feed.entries if e.get("title")
)
js
const allText = feed.entries
  .filter((e) => e.title)
  .map((e) => `标题:${e.title}`)
  .join('\n')

next:取第一项

next(迭代器, 默认值) 取出第一个元素;给了默认值就找不到也不抛。常和生成器表达式一起用。

python
task = next(
    (t for t in tasks if t["status"] == "ready"),
    None,
)
js
const task = tasks.find((t) => t.status === 'ready') ?? null
PythonJavaScript
next((x for x in xs if cond), None)xs.find((x) => cond) ?? null
不写默认值、空了StopIteration;JS 的 findundefined

while / break

条件还在就转;中间用 break 离开。

python
while candidate.exists():
    n += 1
    candidate = Path(f"{stem}-{n}{suffix}")

for item in catalog:
    if item["ref"] in loaded:
        break
js
while (fs.existsSync(candidate)) {
  n += 1
  candidate = `${stem}-${n}${suffix}`
}

for (const item of catalog) {
  if (loaded.has(item.ref)) break
}

while True + break 是「常驻等到某个条件」;for + break 是「扫到就停」。

下一页叠:切片、拍平、排序。这些是在列表上再加一层操作。