从带有map的类方法调用NumPy时出现Python错误

时间:2017-11-05 15:03:49

标签: python numpy

以下代码会引发错误:

Traceback (most recent call last):
  File "", line 25, in <module>
    sol = anna.main()
  File "", line 17, in main
    sol = list(map(self.eat, self.mice))
  File "", line 12, in eat
    calc = np.sqrt((food ** 5))
AttributeError: 'int' object has no attribute 'sqrt'

代码:

import numpy as np
#import time

class anaconda():

    def __init__(self):
        self.mice = range(10000)

    def eat(self, food):
        calc = np.sqrt((food ** 5))
        return calc

    def main(self):

        sol = list(map(self.eat, self.mice))
        return sol


if __name__ == '__main__':
    #start = time.time()
    anna = anaconda()
    sol = anna.main()
    print(len(sol))
    #print(time.time() - start)

我相信我犯了一个严重的错误,因为看起来Python将NumPy中的'np'解释为整数,但我没有看到为什么会这样。

5 个答案:

答案 0 :(得分:13)

我会尝试为那些已经给出的人添加一个精确的答案。 numpy.sqrt有一些math.sqrt没有的限制。

import math
import numpy  # version 1.13.3

print(math.sqrt(2 ** 64 - 1))
print(numpy.sqrt(2 ** 64 - 1))

print(math.sqrt(2 ** 64))
print(numpy.sqrt(2 ** 64))

返回(使用Python 3.5):

4294967296.0
4294967296.0
4294967296.0
Traceback (most recent call last):
  File "main.py", line 8, in <module>
    print(numpy.sqrt(2 ** 64))
AttributeError: 'int' object has no attribute 'sqrt'

实际上,2 ** 64等于18,446,744,073,709,551,616,并且根据C数据类型的标准(版本C99),long long unsigned integer类型至少包含{{1}之间的范围并且包含0

发生18,446,744,073,709,551,615因为AttributeError,看到它不知道如何处理的类型(转换为C数据类型后),默认调用numpy方法在对象上(但不存在)。如果我们使用浮点数而不是整数,那么一切都可以使用sqrt

numpy

返回:

import numpy  # version 1.13.3

print(numpy.sqrt(float(2 ** 64)))

因此,您可以在4294967296.0 替换numpy.sqrt,而不是在math.sqrt替换calc = np.sqrt(food ** 5)

我希望这个错误现在对你更有意义。

答案 1 :(得分:3)

正如其他人注意到的那样,归结为import numpy as np print(np.sqrt(7131 ** 5)) print(np.sqrt(7132 ** 5)) # 4294138928.9 Traceback (most recent call last): File "main.py", line 4, in <module> print(np.sqrt(7132 ** 5)) AttributeError: 'int' object has no attribute 'sqrt' 有效但for a = first element, b = last element; a != last; a = next a while ( ( b != first element ) and (a + b > z) ) b = previous elemnet of b if a + b == z return true 会返回错误:

 def as_json
 hash = {}
 hash["title"] = calendar_title
 #hash["description"] = calendar_description
 hash["start"] = start_at.strftime("%Y-%m-%d")
 hash["end"] = end_at.strftime("%Y-%m-%d")
 hash["url"] = "/admin/appointments/#{id}"
 hash["base_amount"] = base_amount
 hash["start_at"] = start_at
 hash["end_at"] = end_at
 hash["tech_id"] = technician_id
 hash["asset_id"] = asset_id
 hash["customer_name"] = customer.full_name(false)
# hash["customer_id"] = customer_id
 hash["id"] = id
# hash["cust_addresses"] = customer.addresses
 hash["address"] = address
#   client_host = ClientHost::Location.find_by_id(address.client_host_locations_id)
# hash["customer_email"] = customer.email
# hash["customer_wholesale"] = customer.wholesale?
# hash["customer_tax_exempt"] = customer.tax_exempt?
# hash["vehicles"] = self.get_vehicles
end

def get_vehicles

vehicles = []
self.appointment_vehicles.each do |av|
  hash = {}
  hash["appointment_vehicle"] = av
  hash["total_amount"] = av.total_amount
  hash["vehicle"] = av.vehicle
  hash["package_display_title"] = av.package.display_title
  hash["package_amount"] = av.package.amount
  hash["upgrades"] = self.get_upgrades(av.upgrades)
  vehicles.push(hash)
end
return vehicles

由于np.sqrt docs没有提及论点的任何界限,我认为这是一个numpy bug。

答案 2 :(得分:2)

您可以使用内置函数math.sqrt替换numpy,如下所示:

import math  

class anaconda():

    def __init__(self):
        self.mice = range(10000)

    def eat(self, food):
        calc = math.sqrt(food ** 5)
        return calc

    def main(self):

        sol = list(map(self.eat, self.mice))
        return sol


if __name__ == '__main__':
    anna = anaconda()
    sol = anna.main()
    print(len(sol))

我认为您的代码问题是您可能已达到限制(不确定为什么会引起混淆错误)因为10000 ** 5是一个非常大的数字。 您可以通过将范围(10000)减小到范围(1000)来检查这一点。您会注意到您的代码运行完全正常:

import numpy as np  

class anaconda():

    def __init__(self):
        self.mice = range(1000)

    def eat(self, food):
        calc = np.sqrt((food ** 5))
        return calc

    def main(self):

        sol = list(map(self.eat, self.mice))
        print sol
        return sol


if __name__ == '__main__':
    anna = anaconda()
    sol = anna.main()
    print(len(sol))

只需将范围(10000)缩小到范围(1000)

,就可以完美地运行

答案 3 :(得分:1)

纯Python

实际上,您既不需要numpy也不需要math,因为sqrt(x) is x**0.5。所以:

sqrt(x**5) = x ** (5/2) = x ** 2.5

这意味着您可以用以下代码替换您的代码:

class anaconda():
    def __init__(self):
        self.mice = range(10000)

    def eat(self, food):
        calc = food ** 2.5
        return calc

    def main(self):
        sol = list(map(self.eat, self.mice))
        return sol


if __name__ == '__main__':
    anna = anaconda()
    sol = anna.main()
    print(len(sol))

NumPy的

如果你想使用NumPy,你可以享受这样一个事实:你可以像使用标量一样使用数组:

import numpy as np

class anaconda():

    def __init__(self):
        self.mice = np.arange(10000)

    def eat(self, food):
        return food ** 2.5

    def main(self):
        return self.eat(self.mice)


if __name__ == '__main__':
    anna = anaconda()
    sol = anna.main()
    print(len(sol))

短重构

删除所有不需要的面向对象的奇怪名称,您的代码变为:

import numpy as np
print(np.arange(10000) ** 2.5)

答案 4 :(得分:0)

这可能不是您的确切情况,但是如果您想取一个大数的平方根并且想要控制结果的精度,请转到math.sqrt()或{{1} }不会有太大用处,因为您的结果最终将是浮点数,并且对于足够大的输入,这将达到浮点数的限制。

x ** 0.5特定情况的一种可能性是研究平方根算法的仅整数实现,例如flyingcircus.util.isqrt()(免责声明:我是flyingcircus的主要作者)。

或者,对于更通用的解决方案,可以考虑使用gmpy(或任何其他具有Python绑定的任意精度库)。