Ошибка 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 интерпретирует "np" из NumPy как целое число, но я не вижу, почему это так.
Ответы
Ответ 1
Я попытаюсь добавить точный ответ на те, которые уже были даны. 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
содержит, по крайней мере, диапазон между 0
и 18,446,744,073,709,551,615
.
AttributeError
происходит потому, что numpy
, вид того, что он не знает, как обрабатывать (после преобразования в тип данных C), по умолчанию используется метод sqrt
для объекта (но это doesn ' t существует). Если мы используем float вместо целых чисел, то все будет работать с помощью numpy
:
import numpy # version 1.13.3
print(numpy.sqrt(float(2 ** 64)))
возвращает:
4294967296.0
Поэтому вместо замены numpy.sqrt
на math.sqrt
вы можете вместо этого заменить calc = np.sqrt(food ** 5)
на calc = np.sqrt(float(food ** 5))
в вашем коде.
Я надеюсь, что эта ошибка будет иметь для вас больше смысла.
Ответ 2
Как заметили другие, это сводится к тому, что np.sqrt(7131 ** 5)
работает, но np.sqrt(7132 ** 5)
возвращает ошибку:
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'
Так как np.sqrt
docs не упоминает никаких ограничений в аргументе, я бы счел это ошибкой numpy.
Ответ 3
Вы можете заменить numpy встроенной функцией math.sqrt следующим образом:
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)
Ответ 4
Обычный Python
На самом деле вам не нужны ни numpy
, ни math
, потому что sqrt(x)
- 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)