【问题标题】:Assigning value in a while comparison expression在while比较表达式中赋值
【发布时间】:2010-01-14 00:59:14
【问题描述】:

您好,我想知道是否可以在代码的 while 比较部分中分配一个值。

这是目前的代码示例

startIndex = find(target, key, startIndex)
while( startIndex != -1):
    matchesFound += 1
    startIndex = find(target, key, startIndex + 1)
return matchesFound

我想要做的是将 startIndex = find(target, key, startIndex) 移动到 while 比较表达式中,所以它看起来像这样

while( (startIndex = find(target, key, startIndex)) != -1):
    matchesFound += 1
    startIndex + 1
return matchesFound

如果不是,那么更好的重构是什么?

谢谢

编辑 在尝试著名的 6.001 模块之前,我正在学习 MIT Open 课件 6.00

【问题讨论】:

  • 答案仍然是否定的。重复:stackoverflow.com/questions/1663995/…
  • 这两个是一样的吗?在第一种情况下,您首先使用startIndex 调用find,而在后一种情况下,您使用startIndex+1 调用它。
  • 是的,你是对的,彼得,我已经更正了
  • @Sam,有了这个更正,即使在 C 语言中,我也会称该代码丑陋。:) 在两个地方更改 startIndex 会使下一个接触代码的程序员绊倒。

标签: python


【解决方案1】:

如果由于某种原因您无法从所搜索的任何内容中使用更合适的方法,则这相当于问题中的工作代码:

start = 0
count = 0
for match in iter(lambda: find(target, key, start), -1):
  count += 1
  start = match + 1
return count

但是,编写用于查找这些匹配项的迭代器,“转换”您当前的查找功能,您将获得最大的收益:

def findall(target, key, start=0):
  for match in iter(lambda: find(target, key, start), -1):
    yield match
    start = match + 1

然后从那算起:

count = sum(1 for m in findall(target, key))

【讨论】:

  • +1 首先是 Pythonic (更重要的是)实际上与 OP 在行为上的第一个示例相匹配。
  • 我不确定更多的pythonic,循环半是一个很好的候选者,但问题似乎只是示例代码,这种形式的 iter() 可能在他真正在做什么。 :)(我还假设 startIndex 从 0 开始,但没有说明,但显然这很容易改变。)
  • 我在做 MIT 6.00 课程的作业,这个作业只是写了两个函数(一个是迭代的,一个是递归的)来计算一个关键字符串在目标字符串中出现的次数
  • 让我们说“优雅”而不仅仅是“Pythonic”,因为正如你所说,即使是循环半也绝对是 Pythonic。即使不是,我仍然会给你 +1 以很好地使用 sentinel 参数! :)
  • 喜欢这个答案,但是 find 函数是 string.find(key,start) 。仍然很棒的答案。
【解决方案2】:

您正在用 Python 编写 C。

试试:

startIndex = -1
while True:
    startIndex = find(target, key, startIndex + 1)
    if startIndex < 0:
        break
    matchesFound += 1
return matchesFound

或者甚至:

return target.count(key)

【讨论】:

  • 这与 OP 的代码不匹配。 startIndex 显然需要在第一个调用之后增加 1。
  • +1 用于识别为 C 约定...尽管我确信它在其他语言中是合法的。
  • 如果我也是用 C 编程的话,我实际上做了 14 个月的实习
  • 您需要括号外的 +1,看看我的回答。
  • 不,第一次迭代你传递 1 (0 + 1) 作为 find 的第三个参数,我传递 0。
【解决方案3】:

PEP 572 被接受后,就可以这样做了:

while (startIndex := find(target, key, startIndex)) != -1:
    matchesFound += 1
    startIndex + 1
    return matchesFound

它将包含在 Python 3.8 中。

此更改将使 python 代码更小。考虑以下标准库代码:

while True:
    line = fp.readline()
    if not line:
        break
    m = define_rx.match(line)
    if m:
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    else:
        m = undef_rx.match(line)
        if m:
            vars[m.group(1)] = 0

会这样改进:

while line := fp.readline():
    if m := define_rx.match(line):
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    elif m := undef_rx.match(line):
        vars[m.group(1)] = 0

【讨论】:

    【解决方案4】:

    不,你不能在 Python 中做到这一点。我认为 Python 不允许这样做的主要原因是为了避免由于混淆赋值和相等检查而导致的频繁错误。

    Python 声称将可读代码作为主要准则,所以我认为您的原始代码很好。无需重构...

    【讨论】:

      【解决方案5】:

      我会这样做

      startIndex=0
      while 1:
          startIndex = find(target, key, startIndex+1)
          if startIndex == -1: break
          matchesFound += 1
      

      您可以像这样在 while 循环中添加更多条件。

      编辑:@OP,将来要计算字符串的匹配,只需使用 count

      >>> mystring = "abc defabc fgh ijkabc blah"
      >>> mystring.count("abc")
      3
      >>>
      

      【讨论】:

      • 显然也与 OP 的代码不匹配,其中 startIndex 在第一次调用之后提前通过 1 传递。
      【解决方案6】:

      编辑。

      我们像这样重构它。

      matches = [ k for k in range(len(target)-len(key)) if target[k:].startswith(key) ]
      matchesFound = len(matches)
      

      我们不需要 C 风格的条件和赋值合并。

      您很少只想要计数;实际位置是免费提供的。

      【讨论】:

        猜你喜欢
        • 2018-04-01
        • 1970-01-01
        • 2017-05-23
        • 2017-03-12
        • 2018-04-20
        • 2015-04-18
        • 1970-01-01
        • 2014-01-17
        • 1970-01-01
        相关资源
        最近更新 更多