Saya sedang mengerjakan jitclass di mana salah satu metode dapat menerima argumen input int, float, atau numpy.ndarray. Saya harus dapat menentukan apakah argumennya adalah dan array atau salah satu dari dua jenis lainnya. Saya sudah mencoba menggunakan isinstance seperti yang ditunjukkan pada metode interp di bawah ini:

spec = [('x', float64[:]),
        ('y', float64[:])]


@jitclass(spec)
class Lookup:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def interp(self, x0):
        if isinstance(x0, (float, int)):
            result = self._interpolate(x0)
        elif isinstance(x0, np.ndarray):
            result = np.zeros(x0.size)
            for i in range(x0.size):
                result[i] = self._interpolate(x0[i])
        else:
            raise TypeError("`interp` method can only accept types of float, int, or ndarray.")
        return result

    def _interpolate(self, x0):
        x = self.x
        y = self.y
        if x0 < x[0]:
            return y[0]
        elif x0 > x[-1]:
            return y[-1]
        else:
            for i in range(len(x) - 1):
                if x[i] <= x0 <= x[i + 1]:
                    x1, x2 = x[i], x[i + 1]
                    y1, y2 = y[i], y[i + 1]

                    return y1 + (y2 - y1) / (x2 - x1) * (x0 - x1)

Tapi saya mendapatkan kesalahan berikut:

numba.errors.TypingError: Failed at nopython (nopython frontend)
Failed at nopython (nopython frontend)
Untyped global name 'isinstance': cannot determine Numba type of <class 'builtin_function_or_method'>
File "Lookups.py", line 17
[1] During: resolving callee type: BoundFunction((<class 'numba.types.misc.ClassInstanceType'>, 'interp') for instance.jitclass.Lookup#2167664ca28<x:array(float64, 1d, A),y:array(float64, 1d, A)>)
[2] During: typing of call at <string> (3)

Apakah ada cara untuk menentukan apakah argumen input bertipe tertentu saat menggunakan jitclasses atau dalam mode nopython?

Sunting

Saya seharusnya menyebutkan ini sebelumnya tetapi menggunakan type bawaan juga sepertinya tidak berfungsi. Misalnya jika saya mengganti metode interp dengan:

def interp(self, x0):
        if type(x0) == float or type(x0) == int:
            result = self._interpolate(x0)
        elif type(x0) == np.ndarray:
            result = np.zeros(x0.size)
            for i in range(x0.size):
                result[i] = self._interpolate(x0[i])
        else:
            raise TypeError("`interp` method can only accept types of float, int, or ndarray.")
        return result

Saya mendapatkan kesalahan berikut:

numba.errors.TypingError: Failed at nopython (nopython frontend)
Failed at nopython (nopython frontend)
Invalid usage of == with parameters (class(int64), Function(<class 'float'>))

Yang saya pikir mengacu pada perbandingan python float dan int64 numba ketika saya melakukan sesuatu seperti lookup_object.interp(370) misalnya.

2
pbreach 14 Agustus 2017, 04:13

2 jawaban

Jawaban Terbaik

Anda kurang beruntung jika perlu menentukan dan membandingkan jenis di dalam fungsi numba jitclass atau nopython jit karena isinstance tidak didukung sama sekali dan type mendukung hanya pada beberapa tipe numerik dan tupel bernama (perhatikan bahwa ini hanya mengembalikan tipe - ini tidak cocok untuk perbandingan - karena == tidak diimplementasikan untuk kelas di dalam fungsi numba).

Pada Numba 0.35 satu-satunya built-in yang didukung adalah (sumber: dokumentasi numba):

Fungsi bawaan berikut didukung:

abs()
bool
complex
divmod()
enumerate()
float
int: only the one-argument form
iter(): only the one-argument form
len()
min()
max()
next(): only the one-argument form
print(): only numbers and strings; no file or sep argument
range: semantics are similar to those of Python 3 even in Python 2: a range object is returned instead of an array of values.
round()
sorted(): the key argument is not supported
type(): only the one-argument form, and only on some types (e.g. numbers and named tuples)
zip()

Saran saya: Gunakan kelas Python normal dan tentukan jenisnya di sana dan kemudian teruskan ke numba.njitfungsi yang sesuai:

import numba as nb
import numpy as np

@nb.njit
def _interpolate_one(x, y, x0):
    if x0 < x[0]:
        return y[0]
    elif x0 > x[-1]:
        return y[-1]
    else:
        for i in range(len(x) - 1):
            if x[i] <= x0 <= x[i + 1]:
                x1, x2 = x[i], x[i + 1]
                y1, y2 = y[i], y[i + 1]

                return y1 + (y2 - y1) / (x2 - x1) * (x0 - x1)

@nb.njit
def _interpolate_many(x, y, x0):
    result = np.zeros(x0.size, dtype=np.float_)
    for i in range(x0.size):
        result[i] = _interpolate_one(x, y, x0[i])
    return result

class Lookup:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def interp(self, x0):
        if isinstance(x0, (float, int)):
            result = _interpolate_one(self.x, self.y, x0)
        elif isinstance(x0, np.ndarray):
            result = _interpolate_many(self.x, self.y, x0)
        else:
            raise TypeError("`interp` method can only accept types of float, int, or ndarray.")
        return result
2
MSeifert 15 Agustus 2017, 18:13

Gunakan type()?

blah = []
if type(blah) is list:
    print "Is a list"

blah = 5
if type(blah) is int:
    print "we have an int"

Yaitu:

>>> blah = 5
>>> type(blah)
<type 'int'>
>>>
-1
VeNoMouS 14 Agustus 2017, 01:37