I have a question about the use of vectorize in new.instancemethod:

Using vectorize with *args requires adjustment to the number of
arguments, nin = nargs. This works when it is used with a function.
However, I don't manage to set nin when using vectorize with a method
created with new.instancemethod.

I would like to do:

def funcm(self,x,*args):
 ...

class D(object):
    def __init__(self):
        vecfunc = vectorize(funcm)
        vecfunc.nin = 2
        self.funcm = new.instancemethod(vecfunc,self,A)

But, calling D().funcm still causes a value error. I managed to do it
by setting vecfunc.nin = None.
What is the correct or best way to do this? I needed it when I wanted
to correct scipy.stats.distributions.

Below (and as attachment) is a script that summarizes what I figured
out about the use of vectorize with *args.
I did not find any documentation for this case, I got the information
by trial and error and hints in the bug reports.

Josef

'''
Nin adjustment in np.vectorize with *args
=========================================

* Problem: simple use of vectorize with *args raises exception::

  File "C:\Programs\Python24\Lib\site-packages\numpy\lib
\function_base.py", line 1636, in __call__
    raise ValueError, "mismatch between python function inputs"\
  ValueError: mismatch between python function inputs and received
arguments

* solution adjust nin directly, either set nin to the correct number
of arguments
  or set nin to None

* with functions both ways of adjusting nin work, (case 2 and 3)

* with new.instance method, the only way, I managed to get it to work
is by
  setting nin = None (case E). Setting nin = nargs did not work (case
C and D)


with functions
--------------

* case 0: function without vectorize
* case 1: function with vectorize -> broken
* case 2: function with vectorize, with nin adjustment -> works
* case 3: function with vectorize, with nin adjustment, nin = None ->
works

with class and new.instancemethod
---------------------------------

* case A: class without vectorize -> works
* case B: class with vectorize -> broken: argument miss match
* case C: class with vectorize with nin adjustment -> broken
* case D: class with vectorize with nin adjustment -> broken
* case E: class with vectorize with nin adjustment, nin = None ->
works

Motivation:
-----------

vectorize (sgf) in scipy.stats.distribution does not work in cases
where there
is no correct nin adjustment.
Example for new.instancemethod, that looks broken, is self._ppf in
class rv_discrete.


'''


import new
import numpy as np
from numpy import vectorize

def func1(x,*args):
    print 'args = ', args
    print 'x = ', x
    return np.sum(x)

def funcm(self,x,*args):
    ''' function for use as instance method'''
    print 'args = ', args
    print 'x = ', x
    return np.sum(x)

# case 0: function without vectorize
print 'func1(1,*(2,))'
func1(1,*(2,))

# case 1: function with vectorize -> broken
vecfunc = vectorize(func1)

print 'vecfunc(1):'
vecfunc(1)
print 'vecfunc(1,3):'
try:
    vecfunc(1,3)
except ValueError,e:
    print e

print 'vecfunc(1,*(2,))'
try:
    vecfunc(1,*(2,))
except ValueError,e:
    print e

# case 2: function with vectorize, with nin adjustment -> works

vecfunc2 = vectorize(func1)
vecfunc2.nin = 2

print 'vecfunc2(1):'
vecfunc2(1)
print 'vecfunc2(1,3):'
vecfunc2(1,3)
print 'vecfunc2(1,*(2,))'
vecfunc2(1,*(2,))

# case 3: function with vectorize, with nin adjustment, nin = None ->
works

vecfunc3 = vectorize(func1)
vecfunc3.nin = None

print 'vecfunc3(1):'
vecfunc3(1)
print 'vecfunc3(1,3):'
vecfunc3(1,3)
print 'vecfunc3(1,*(2,))'
vecfunc3(1,*(2,))
print 'vecfunc3(1,*(2,5))'
vecfunc3(1,*(2,5))


# with class and new.instancemethod

# case A: class without vectorize -> works

class A(object):
    def __init__(self):
        self.funcm = new.instancemethod(funcm,self,A)

aa = A()
#print dir(aav)

print 'A: aav.funcm(5)'
aa.funcm(5)
print 'A: aav.funcm(5,2)'
aa.funcm(5,2)
print 'A: aav.funcm(5,*(2,))'
aa.funcm(5,*(2,))

# case B: class with vectorize -> broken: argument miss match

class B(object):
    def __init__(self):
        self.funcm = new.instancemethod(vectorize(funcm),self,A)

aav = B()
#print dir(aav)

print 'B: aav.funcm(5)'
aav.funcm(5)
print 'B: aav.funcm(5,2)'
try:
    aav.funcm(5,2)
except ValueError,e:
    print e
print 'B: aav.funcm(5,*(2,))'
try:
    aav.funcm(5,*(2,))
except ValueError,e:
    print e

# case C: class with vectorize with nin adjustment -> broken
# AttributeError: 'instancemethod' object has no attribute 'nin'


class C(object):
    def __init__(self):
        self.funcm = new.instancemethod(vectorize(funcm),self,A)
        #self.funcm.nin = 2
        try:
            self.funcm.nin = 2
        except AttributeError,e:
            print e

aav = C()
#print dir(aav)

print 'C: aav.funcm(5)'
aav.funcm(5)

print 'C: aav.funcm(5,2)'
try:
    aav.funcm(5,2)
except ValueError,e:
    print e
print 'C: aav.funcm(5,*(2,))'
try:
    aav.funcm(5,*(2,))
except ValueError,e:
    print e

# case D: class with vectorize with nin adjustment -> broken
# nin is not correctly used by vectorize

class D(object):
    def __init__(self):
        # define the vectorized function
        vecfunc = vectorize(funcm)
        vecfunc.nin = 2
        self.funcm = new.instancemethod(vecfunc,self,A)
        #self.funcm.nin = 2
        try:
            self.funcm.nin = 2
        except AttributeError,e:
            print e

aav = D()
#print dir(aav)

print 'D: aav.funcm(5)'
aav.funcm(5)

print 'D: aav.funcm(5,2)'
try:
    aav.funcm(5,2)
except ValueError,e:
    print e
print 'D: aav.funcm(5,*(2,))'
try:
    aav.funcm(5,*(2,))
except ValueError,e:
    print e


# case E: class with vectorize with nin adjustment, nin = None ->
works
# nin is calculated by vectorize


class E(object):
    def __init__(self):
        vecfunc = vectorize(funcm,otypes='d')
        vecfunc.nin = None  # remove nin at let vectorize do the work
        self.funcm = new.instancemethod(vecfunc,self,A)
        #self.funcm.nin = 2
        try:
            self.funcm.nin = 2
        except AttributeError,e:
            print e

aav = E()
#print dir(aav)

print 'E: aav.funcm(5)'
aav.funcm(5)

print 'E: aav.funcm(5,2)'
try:
    aav.funcm(5,2)
except ValueError,e:
    print e
print 'E: aav.funcm(5,*(2,))'
try:
    aav.funcm(5,*(2,))
except ValueError,e:
    print e

aav.funcm([1,2,5.2])
aav.funcm([1,2,5.2],*(2,))
res = aav.funcm(np.array([1,2,5.2]),*(2,))
print res
_______________________________________________
Numpy-discussion mailing list
Numpy-discussion@scipy.org
http://projects.scipy.org/mailman/listinfo/numpy-discussion

Reply via email to