Thanks for this, very informative! :-) Chris
On 06/10/2010 17:35, Friedrich Romstedt wrote: > 2010/10/5 Chris Withers<ch...@simplistix.co.uk>: >> Hi All, >> >> I can't find any docs on this behavior. >> >> So, I have a python function. To keep it simple, lets just do addition: >> >> def add(x,y): >> print x,y >> retun x+y >> >> So, I can turn this into a ufunc as follows: >> >> uadd = np.frompyfunc(add,2,1) > > As a side remark, note that this will always return dtype=numpy.object > arrays. Maybe numpy.vectorize() is more appropriate for your > use-case. > >> Now, I can apply it to an array: >> >> >>> uadd.accumulate(np.arange(3,10)) >> 3 4 >> 7 5 >> 12 6 >> 18 7 >> 25 8 >> 33 9 >> array([3, 7, 12, 18, 25, 33, 42], dtype=object) >> >> Okay, but where did the initial 3 come from? >> http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.accumulate.html#numpy.ufunc.accumulate >> suggests that: >> >> r = np.empty(len(A)) >> t = op.identity # op = the ufunc being applied to A's elements >> for i in xrange(len(A)): >> t = op(t, A[i]) >> r[i] = t >> return r > > I see from the behaviour, that the implementation makes use of the > following behaviour of the identity ``op.identity`` with respect to > ``op``: > >>>> op(op.identity, X) == X > True > > So the implementation acts in agnosticism of ``op.identity`` by > assuming that the first call of ``t = op(t, A[i])`` in your example > will just yield ``A[0]``, while i == 0. > > This is the work flow: > > [ t = op.identity ] # in brackets because it cannot be executed, it's > pseudo-code > > i = 0 > ===== > t = op(t, A[0]) = A[0] > r[0] = t = A[0] > > i = 1 > ===== > t = op(t, A[1]) = op(A[0], A[1]) > r[1] = t > > i = 2 > ===== > t = op(t, A[2]) = op(op(A[0], A[1]), A[2]) > r[2] = t > > and so on ... clear now? > > Friedrich > >> ...but: >> >> >>> print uadd.identity >> None > > It's simply not set, and will also not be used. > >> ...and: >> >> >>> add(None,3) >> None 3 >> Traceback (most recent call last): >> File "<stdin>", line 1, in<module> >> File "<stdin>", line 3, in add >> TypeError: unsupported operand type(s) for +: 'NoneType' and 'int' > > As said, the code in the docs is just pseudo-code, it's not the actual > (C?) implementation, it just has the same semantics. > >> So, where is the reason that the 3 ends up in the output array documented? >> >> Also, what if I want to specify the identity of my newly created ufunc? >> I have a case where I want to specify it as zero: >> >> >>> uadd.identity = 0 >> Traceback (most recent call last): >> File "<stdin>", line 1, in<module> >> AttributeError: attribute 'identity' of 'numpy.ufunc' objects is not >> writable > > I think you have to write an own class for this. You cannot subclass > numpy.ufunc ("it's not an acceptable base class" Python says). > _______________________________________________ > NumPy-Discussion mailing list > NumPy-Discussion@scipy.org > http://mail.scipy.org/mailman/listinfo/numpy-discussion > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ -- Simplistix - Content Management, Batch Processing & Python Consulting - http://www.simplistix.co.uk _______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion