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