/ Błąd / Python podczas wywoływania NumPy z metody klasy za pomocą map - python, numpy

Błąd Pythona podczas wywoływania NumPy z metody klasy z mapą - python, numpy

Poniższy kod generuje błąd:

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"

Kod:

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)

Wydaje mi się, że popełniłem poważny błąd, ponieważ wygląda na to, że Python interpretuje „np” z NumPy jako liczbę całkowitą, ale nie mam pojęcia, dlaczego tak jest.

Odpowiedzi:

11 dla odpowiedzi nr 1

Spróbuję dodać dokładną odpowiedź do tych, które już zostały podane. numpy.sqrt ma pewne ograniczenia, które math.sqrt nie ma.

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))

zwraca (z 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"

W rzeczywistości, 2 ** 64 jest równe 18,446,744,073,709,551,616 i zgodnie ze standardem typów danych C (wersja C99), long long unsigned integer typ zawiera przynajmniej zakres pomiędzy 0 i 18,446,744,073,709,551,615 w zestawie.

The AttributeError występuje, ponieważ numpy, widząc typ, którego nie umie obsługiwać (po konwersji na typ danych C), domyślnie wywołuje funkcję sqrt metoda na obiekcie (ale to nie istnieje). Jeśli użyjemy liczb zmiennoprzecinkowych zamiast liczb całkowitych, wszystko będzie działać przy użyciu numpy:

import numpy  # version 1.13.3

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

zwraca:

4294967296.0

Więc zamiast zastępować numpy.sqrt przez math.sqrt, możesz alternatywnie wymienić calc = np.sqrt(food ** 5) przez calc = np.sqrt(float(food ** 5)) w twoim kodzie.

Mam nadzieję, że ten błąd będzie dla ciebie bardziej sensowny.


3 dla odpowiedzi № 2

Jak zauważyli inni, sprowadza się to do tego np.sqrt(7131 ** 5) działa ale np.sqrt(7132 ** 5) zwraca błąd:

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"

Od np.sqrt docs nie wspominając o żadnych ograniczeniach argumentu, uważam to za dziwaczny błąd.


2 dla odpowiedzi nr 3

Możesz zastąpić numpy wbudowaną funkcją math.sqrt w następujący sposób:

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))

Myślę, że problemem twojego kodu jest to, że typrawdopodobnie osiągają limit (nie jestem jeszcze pewien, dlaczego podnosi ten mylący błąd), ponieważ 10000 ** 5 to naprawdę duża liczba. Możesz to sprawdzić, zmniejszając swój zasięg (10000) do zasięgu (1000). Zauważysz, że Twój kod działa idealnie dobrze:

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))

Działa to idealnie dobrze, po prostu zmniejszając zasięg (10000) do zasięgu (1000)


1 dla odpowiedzi nr 4

Tak naprawdę nie potrzebujesz numpy ani math bo sqrt(x) jest x**0.5. Więc:

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

Oznacza to, że możesz zastąpić swój kod:

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

Jeśli chcesz korzystać z NumPy, możesz cieszyć się faktem, że możesz pracować z tablicami tak, jakby były skalarami:

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))

Krótki refaktor

Usuwając wszystkie niepotrzebne nazwy obiektowe z dziwnymi nazwami, kod staje się:

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