From: Ivan V. i B. <iv...@ca...> - 2006-10-16 10:48:18
Attachments:
signature.asc
|
Looking at the ``ophelper()`` decorator in the ``expressions`` module of Numexpr, I see the following code is used to check/replace arguments of operators:: for i, x in enumerate(args): if isConstant(x): args[i] =3D x =3D ConstantNode(x) if not isinstance(x, ExpressionNode): return NotImplemented This looks like operations on unknown kinds of arguments use the default Python behaviour. However, this yields some strange results: >>> import numpy >>> a =3D numpy.array([1,1,1]) >>> import numexpr >>> numexpr.evaluate('a < [0,0,0]') array(True, dtype=3Dbool) This is odd because the comparison was not element-wise, but object-wise (between a VariableNode and an -unsupported- python list). Since Numexpr only understands scalar constants, variables and some functions (the last two are expression nodes), it seems more correct to me to simply forbid unsupported objects to avoid surprises, so the previous code may look like this:: for i, x in enumerate(args): if isConstant(x): args[i] =3D ConstantNode(x) elif not isinstance(x, ExpressionNode): raise TypeError( "unsupported object type: %s", type(x) ) Do you think this is OK, or am I wrong or missing something? Cheers, :: Ivan Vilata i Balaguer >qo< http://www.carabos.com/ C=C3=A1rabos Coop. V. V V Enjoy Data "" |
From: Tim H. <tim...@ie...> - 2006-10-16 16:26:48
|
Ivan Vilata i Balaguer wrote: > Looking at the ``ophelper()`` decorator in the ``expressions`` module of > Numexpr, I see the following code is used to check/replace arguments of > operators:: > > for i, x in enumerate(args): > if isConstant(x): > args[i] = x = ConstantNode(x) > if not isinstance(x, ExpressionNode): > return NotImplemented > > This looks like operations on unknown kinds of arguments use the default > Python behaviour. However, this yields some strange results: > > >>>> import numpy >>>> a = numpy.array([1,1,1]) >>>> import numexpr >>>> numexpr.evaluate('a < [0,0,0]') >>>> > array(True, dtype=bool) > > This is odd because the comparison was not element-wise, but object-wise > (between a VariableNode and an -unsupported- python list). Since > Numexpr only understands scalar constants, variables and some functions > (the last two are expression nodes), it seems more correct to me to > simply forbid unsupported objects to avoid surprises, so the previous > code may look like this:: > > for i, x in enumerate(args): > if isConstant(x): > args[i] = ConstantNode(x) > elif not isinstance(x, ExpressionNode): > raise TypeError( "unsupported object type: %s", > type(x) ) > > Do you think this is OK, or am I wrong or missing something? That looks right. I'm not entirely happy with this fix; I believe that returning NotImplemented was intentional with the idea that we might someday want to use the NotImplemented machinery. That said, I can't think of a better fix and I don't see us using the NotImplemented machinery anytime soon, so I imagine it should go in. -tim |
From: Ivan V. i B. <iv...@ca...> - 2006-10-16 16:37:31
Attachments:
signature.asc
|
En/na Tim Hochberg ha escrit:: > Ivan Vilata i Balaguer wrote: >> >> for i, x in enumerate(args): >> if isConstant(x): >> args[i] =3D ConstantNode(x) >> elif not isinstance(x, ExpressionNode): >> raise TypeError( "unsupported object type: %s", >> type(x) ) >> >> Do you think this is OK, or am I wrong or missing something? >=20 > That looks right. I'm not entirely happy with this fix; I believe that = > returning NotImplemented was intentional with the idea that we might=20 > someday want to use the NotImplemented machinery. That said, I can't=20 > think of a better fix and I don't see us using the NotImplemented=20 > machinery anytime soon, so I imagine it should go in. Maybe placing a comment there should be enough for future reference. By the way, I noticed that I splipped a bad string interpolation there, it should be ``"unsupported object type: %s" % type(x)``. Cheers, :: Ivan Vilata i Balaguer >qo< http://www.carabos.com/ C=C3=A1rabos Coop. V. V V Enjoy Data "" |
From: Tim H. <tim...@ie...> - 2006-10-16 17:46:11
|
Ivan Vilata i Balaguer wrote: > En/na Tim Hochberg ha escrit:: > > >> Ivan Vilata i Balaguer wrote: >> >>> for i, x in enumerate(args): >>> if isConstant(x): >>> args[i] = ConstantNode(x) >>> elif not isinstance(x, ExpressionNode): >>> raise TypeError( "unsupported object type: %s", >>> type(x) ) >>> >>> Do you think this is OK, or am I wrong or missing something? >>> >> That looks right. I'm not entirely happy with this fix; I believe that >> returning NotImplemented was intentional with the idea that we might >> someday want to use the NotImplemented machinery. That said, I can't >> think of a better fix and I don't see us using the NotImplemented >> machinery anytime soon, so I imagine it should go in. >> > > Maybe placing a comment there should be enough for future reference. By > the way, I noticed that I splipped a bad string interpolation there, it > should be ``"unsupported object type: %s" % type(x)``. > I went ahead and committed this more or less as is for the time being. I have an idea about how to treat stuff like list and tuple literals. The basic idea is to attempt to convert them to arrays using asarray, then to turn them into pseudo variables. It's all still a little vague, but it should be feasible to have evaluate('a < [1,2,3]') work as it does in numpy. It sounds like work though, so I'm putting it off for now... -tim |