简体   繁体   中英

How to set a custom class as a numpy dtype?

I'm defining a rational number class, like so:

class ratio():
def __init__(q,n:int,d:int=1):
    q.n=n
    q.d=d

And I'm overloading all the binary operators to define them for rational numbers. I would also like to extend these to operate with arrays, like numpy already does with scalars.

I already have enough code for

In: a,b=ratio(2,3),ratio(6,8)
In: print(c:=a*b)
Out: 1/2

Where c is also a ratio. I want to be able to do this:

In: c*np.array([a,b])

Where the output is equivalent to

In: np.array([c*a,c*b])

I figure the best way to do this is to define a new numpy dtype that works with my ratio class methods, but reading the dtype documentation is proving to be too confusing for me. Any tips? Am I even going about this the right way? Also, for the curious, here's all the class methods I have so far

class ratio():
    def __init__(q,n:int,d:int=1):
        q.n=n
        q.d=d
        q.simplify()
    
    def __str__(q):
        return '{}/{}'.format(q.n,q.d)
        
    def value(q):
        return q.n/q.d
    
    def simplify(q):
        g=np.gcd(q.n,q.d)
        q.n//=g
        q.d//=g

    def __mul__(q, r):
        if isinstance(r,ratio): return ratio(q.n*r.n,q.d*r.d)
        elif isinstance(r,int): return ratio(q.n*r,q.d)
        else: return q.value()*r

    def __rmul__(q,r):
        return q.__mul__(r)

    def __truediv__(q, r):
        if isinstance(r,ratio): return ratio(q.n*r.d,q.d*r.n)    
        elif isinstance(r,int): return ratio(q.n,q.d*r)
        else: return q.value()/r
    
    def __rtruediv__(q,r):
        if isinstance(r,int): return ratio(r*q.d,q.n)
        else: return q.value()/r

As said by @juanpa.arrivillaga, there already exists a Fraction Class in the Standard Library.

You can call it as follows:

from fractions import Fraction
f = Fraction(numerator=17, denominator=281)

and it has a method called as_integer_ratio which is basically the same as your simplify.

Edit: Added testing on your use cases:

>>> from fractions import Fraction
>>> import numpy as np
>>> a = Fraction(2,3)
>>> b=Fraction(6,8)
>>> a*b
Fraction(1, 2)
>>> c= a*b
>>> c*np.array([a,b])
array([Fraction(1, 3), Fraction(3, 8)], dtype=object)

Be careful, in your example c=a*b was worth 3/4 which is incorrect .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM