【问题标题】:For loop, SyntaxError: can't assign to function callFor 循环,SyntaxError:无法分配给函数调用
【发布时间】:2017-08-10 13:50:45
【问题描述】:

我正在练习列表推导和嵌套列表推导。作为我练习的一部分,我正在写出等效的 for 循环。这个for循环我无法正确,我相信这是因为我试图在函数调用中分配一个值而不是一个变量。我收到的错误是:

File "<stdin>", line 4
SyntaxError: can't assign to function call

我为这个循环写的代码是:

import math

def squared_primes():
    list = []
    for x in range(1,1000000):
        for q in range(2,math.sqrt(x)+1):
            if all(x % q != 0):
                list.append(x**2)
    print(list)

这个函数试图创建一个完全平方的列表,其根是 1 到 1000000 范围内的素数。

谁能帮我理解我的循环语法到底在哪里出错了?另外,我可以将其作为嵌套列表理解吗?显然,我的列表理解正在崩溃,因为我的 for 循环语法不正确......


解决方案:感谢用户@Evan,我能够修复变量和语法问题,并从this thread 获取了一些关于如何修复all() 语句的提示。

此代码将正确返回 1,1000 的素数平方列表:

def squared_primes():
    list1 = []
    for x in range(1,1000):
        if all(x%q !=0 for q in range(2,int(math.sqrt(x)+1))):
            list1.append(x**2)
    print(list1)

【问题讨论】:

  • 您的意思是将浮点数作为第二个参数传递给内置的 range() 吗?
  • @Evan 不,我的意思是传递一个整数。我尝试将 int(q) 放在范围内......但它仍然无法运行。虽然也许我应该把它留在里面,因为它看起来不像是错误。不过,我会再试一次。
  • 另外,我假设您已经在代码中缩进了 squared_primes() 函数,但是在此处发布时忘记添加额外的四个空格。我可以在没有函数调用错误的情况下运行您的代码,但是如果我删除缩进,我显然会得到缺少缩进的语法错误。我使用 int() 对 math.sqrt(x)+1 表达式进行类型转换以再次测试以避免类型错误。
  • @Evan 抱歉,我确实忘记了这里的缩进。我现在就修。您的列表输出正确吗?你必须在 range 函数之前添加 int(q) 吗?我不知道为什么会出现此错误...我现在要回去尝试。退出 python,以防内存中存储了一些变量。
  • 刚刚意识到,你设置了list=somevariable。 list 是内置类型,不应用作变量名。把它改成其他的,你会在那里解决你的问题。

标签: python for-loop list-comprehension primes nested-loops


【解决方案1】:

此代码将正确返回从 1,1000:

除了它返回 1 作为列表的第一个元素并且 1 的平方根不是素数。让我们修复该故障并将代码重写为正确的函数:

from math import sqrt

def squared_primes(maximum):
    primes = []

    for number in range(2, maximum):
        if all(number % divisor != 0 for divisor in range(2, int(sqrt(number)) + 1)):
            primes.append(number ** 2)
    return primes

print(squared_primes(1000))

顺便说一句,这不是列表理解:

all(x % q !=0 for q in range(2, int(math.sqrt(x) + 1)))

它是一个生成器!如果你想要一个列表理解,你会这样做:

all([x % q !=0 for q in range(2, int(math.sqrt(x) + 1))])

但坚持使用生成器,因为它会以更少的努力使复合材料失败。

当我们要求提供高达 1000000(一百万)或更多的平方列表时,您的代码将开始陷入困境。那时我们需要一个更有效的基于筛的算法,例如:

def squared_primes(maximum):
    sieve = [True] * maximum

    if maximum > 0:
        sieve[0] = False  # zero is not a prime
        if maximum > 1:
            sieve[1] = False # one is not a prime

    for index in range(2, int(maximum ** 0.5) + 1):
        if sieve[index]:
            prime = index
            for multiple in range(prime + prime, maximum, prime):
                sieve[multiple] = False

    return [index * index for index in range(maximum) if sieve[index]]

大约有一百万,此代码返回结果的速度将比基于部门的解决方案快约 20 倍。

而@Evan 的光荣的理解,因为它缺乏你的math.sqrt() 优化,将比任何一个都慢几个数量级(我仍在等待它完成一百万)并开始列出两个不正确的结果。我们可以通过执行以下操作将其与您的修改后的代码相提并论:

from math import sqrt

def squared_primes(maximum):
    return [number ** 2 for number in range(2, maximum) if all(number % divisor for divisor in range(2, int(sqrt(number)) + 1))]

print(squared_primes(1000))

一个列表理解。但同样是错误的方法,所以回头看看基于筛子的实现。

【讨论】:

  • 哎呀,谢谢你;我有点粗心,看到 1 是列表的第一个元素,但你是对的 - 它不是素数。接得好! ?
  • 我刚刚研究了筛算法,我将研究这个解决方案,这似乎非常有效。我最初确实要求从我的代码中输入不超过 1000000 的整数,并注意到这需要一些时间......
  • 我正在查看筛子算法(我去外部资源了解基础知识),并试图找出 while 循环。我知道数字 -= set(...) 表示从原始素数 (2) 的第一个倍数开始,并按该素数计数到最大值,然后从原始完整集合中减去。我没有得到的是质数如何在每次迭代中增加。我看到 prime = numbers.pop() 从未标记的素数中提取值,但这不是从堆的顶部提取的吗?它会先弹出 2,然后继续执行 3 b/c 的 while 循环吗?
  • 我只是感到困惑,因为我认为 pop 会从列表末尾获取一个元素,这将无法使下一次迭代将新数字标记为非质数。显然我一定误解了 .pop()?
  • @Hanzy,有两件事:首先,这不是list.pop(),而是set.pop()。也就是说,set.pop() 应该返回集合的任意元素。但是,当前的现实,特别是从 Python 3.6 开始,字典和 **kwargs 保持它们的顺序,元素是按照它们添加到集合中的顺序弹出的。这可能不是我们将来可以依赖的行为。所以,我用基于list 的实现替换了上面的筛子代码,它的性能略优于set,但也稍微复杂一些。
【解决方案2】:

这很简洁。列表推导非常棒。

def squared_primes(maximum):
    return( [ x**2 for x in range(0,maximum) if all( x % i for i in range(2, x) ) ] )

print(squared_primes(1000000))

【讨论】:

  • 我更新了代码,将列表变量名称替换为 list1,并将 int(q) 传递给 range 函数,但仍然出现相同的错误...
  • 传递 int(q) 不会解决您的问题,因为 q 将是 range() 内置的整数。您需要输入 int(math.sqrt(x)+1) 来修复浮点错误。您仍然收到分配给函数调用错误吗?我仍然很困惑,因为我在运行您的代码时从未遇到过该错误。
  • 我仍然得到相同的分配给函数调用错误,但类型转换 int(math.sqrt(x)+1) 似乎已经解决了这个问题,以及更改了变量名。感谢您的帮助!
  • 我现在正在查看您的列表理解并尝试转换它。我之前在理解中遇到过一些算术函数的问题,但现在这个 for 循环可以工作了,我也许可以让它运行。
  • 您帮助我修复了代码的语法,但我的数学有点错误,并产生了不正确的列表。所以我现在正在修复它(显然 x % q != 0,但我还没有完全达到那个标记)。现在我需要检查是否所有 x % q =! 0,我正在更新代码(在问题中更新)。但我得到错误'bool'对象不可迭代。我应该为此主题打开一个新问题吗?注意:我从this thread 的答案中获取了有关此方法的提示
猜你喜欢
  • 2021-06-06
  • 1970-01-01
  • 1970-01-01
  • 2015-04-23
  • 2021-11-27
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 2017-03-01
相关资源
最近更新 更多