Applying a function recursively

2011-09-10 Thread hetchkay
Hi,
I want to apply a "convert" function on an object as follows:
If the object is of MyType type, invoke the passed in function.
If the object is a dictionary, apply on the keys and values of the
dictionary recursively.
If the object is a set, list or tuple, apply on each element
recursively.
Else, leave the object as is.

I wrote the following code:
def convert(obj, func):
   if isinstance(obj, MyType):
  return func(obj)
   elif isinstance(obj, dict):
  return dict((convert(key, func), convert(value, func)) for key,
value in obj.iteritems())
   elif isinstance(obj, (list, tuple, set)):
  return obj.__class__(convert(x, func) for x in obj)
   else:
  return obj

Is there a better way to do this?
Is there any way I can make this code faster?

Regards,
Krishnan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Applying a function recursively

2011-09-10 Thread hetchkay
>
> I suspect, if you can be explicit about the goal you're aiming for with
> this code, a better design can be found that doesn't require all those
> polymorphism-breaking type checks.
>
It is difficult to explain what I am trying to do, but let me try. I
am mapping data from one hierarchy into another. The mapping rules are
quite complex. I developed a system such that the rules could be
defined as "expressions" of the source hierarchy i.e a particular
entry in the target hierarchy could be represented as an expression of
entries in the source hierarchy. Suppose a point is stored in x, y
coordinates in the source hierarchy, and in polar coordinates in the
target hierarchy, I could write (forget for the moment what sourcePt
is):
pointMapping = {
  sourcePt.key : dict(
 radius = Sqrt(sourcePt.value['x']**2 + sourcePt.value['y']**2),
 angle = Atan(sourcePt.value['y']/sourcePt.value['x']),
   ),
}
The above dictionary is delay-evaluated. sourcePt is an instance of a
class that facilitates the delayed evaluation. Sqrt, Atan etc. are
wrappers to the math functions to facilitate delayed evaluation. When
I encounter a point object, I could 'evaluate' the above mapping for
the point object to get the target dictonary.
The actual requirements are much more involved than this. The
motivation of the design was to enable application developers (who are
not experts in python) to be able to write the mappings. The mappings
also need to be readable.
You could consider this to be some sort of DSL. However, because of
the number of rules involved, I am trying to be as close to Python
expressions as possible. If the target setting is to be a tuple, for
example, I want to be able to write the tuple directly as "( expr1,
expr2 )", rather than, say, "Tuple(expr1, expr2)".
There is also a requirement to validate the mapping on load so that
run-time errors are minimized.
The system we are developing is quite reusable and we have been able
to use it for three different mappings so far. At this point, I am
trying to profile the code and noticed that a non-trivial amount of
time is being spent in the particular function I mentioned in this
thread.

Regards,
Krishnan
-- 
http://mail.python.org/mailman/listinfo/python-list


2.6 and sys.exit()

2009-11-12 Thread hetchkay
Hello,

I have the following in exit.py:
import sys
sys.exit(0)

I now try 'python -i exit.py':

In 2.5, the script exits as I would expect.

In 2.6, the following error is printed:

Traceback (most recent call last):
  File "exit.py", line 2, in 
sys.exit(0)
SystemExit: 0
>>>

I couldn't find anything related to this in "What's new in 2.6".

Is there any way I can get 2.6 to behave like 2.5?

Thank you for your help,

Regards,
H. Krishnan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: 2.6 and sys.exit()

2009-11-12 Thread hetchkay
Hello,

Thanks for your help.

I know what SystemExit is. In 2.5 as well SystemExit is raised when
sys.exit() is called. For example:
try:
  import sys
  sys.exit(0)
except SystemExit:
  print "system exit raised"
  raise

But I don't understand why the interpreter does not exit in 2.6 but
does exit in 2.5. Well, I do not need to understand that but I need to
know how to get the interpreter to exit in 2.6.

Regards,
Krishnan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: 2.6 and sys.exit()

2009-11-12 Thread hetchkay
On Nov 13, 9:50 am, John Yeung  wrote:
> On Nov 12, 11:22 pm, r  wrote:
>
>
>
> > On Nov 12, 10:07 pm, hetchkay  wrote:
> > > I have the following in exit.py:
> > > import sys
> > > sys.exit(0)
>
> > > I now try 'python -i exit.py':
>
> > > In 2.5, the script exits as I would expect.
>
> > > In 2.6, the following error is printed:
>
> > > Traceback (most recent call last):
> > >   File "exit.py", line 2, in 
> > >     sys.exit(0)
> > > SystemExit: 0
>
> > > I couldn't find anything related to this in "What's new in 2.6".
>
> > Look here ;-)
> >http://docs.python.org/library/exceptions.html#exceptions.SystemExit
>
> How does that answer the OP's question?  Namely, how to make 2.6
> behave like 2.5?  (Even saying "You can't make 2.6 behave like 2.5"
> would have been a better answer.)
>
> Failing that, how about something that explains why 2.6 behaves
> differently than 2.5, and why one of them is better or more correct
> than the other?
>
> Personally, I think 2.6's is probably the more correct behavior.
> Specifically, if the point of the -i command line option is to force
> interactive mode after completion of the script (which in this case
> completed with sys.exit), then it should go to interactive mode
> regardless of whether the script terminates "normally" or not.  I
> think 2.5's behavior of allowing interactive mode to be skipped is
> against the spirit of -i.  Unless -i meant something different in 2.5.
>
> Is there some kind of environment variable to set up to control this?
>
> John

I can understand the behavior from a '-i' point of view. My
requirement is somewhat different. Consider a geometry tool that can
be used to create objects, merge objects etc. I have python 'commands'
for doing any of these operations and for saving the objects to a
file. The user could write a file containing a set of commands (in
python format) and load this file in the GUI. Optionally, one of the
commands could be to exit in which case the GUI should shut down. I am
using 'execfile' to execute the file, and this does not exit if the
user has used sys.exit (or even if I expose a command called 'Exit'
which calls sys.exit).

May be I should not be using execfile but I am not sure what else I
should use. The user-written file could contain loops and other
constructs as well.

-Krishnan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: 2.6 and sys.exit()

2009-11-12 Thread hetchkay
On Nov 13, 10:28 am, hetchkay  wrote:
> On Nov 13, 9:50 am, John Yeung  wrote:
>
>
>
> > On Nov 12, 11:22 pm, r  wrote:
>
> > > On Nov 12, 10:07 pm, hetchkay  wrote:
> > > > I have the following in exit.py:
> > > > import sys
> > > > sys.exit(0)
>
> > > > I now try 'python -i exit.py':
>
> > > > In 2.5, the script exits as I would expect.
>
> > > > In 2.6, the following error is printed:
>
> > > > Traceback (most recent call last):
> > > >   File "exit.py", line 2, in 
> > > >     sys.exit(0)
> > > > SystemExit: 0
>
> > > > I couldn't find anything related to this in "What's new in 2.6".
>
> > > Look here ;-)
> > >http://docs.python.org/library/exceptions.html#exceptions.SystemExit
>
> > How does that answer the OP's question?  Namely, how to make 2.6
> > behave like 2.5?  (Even saying "You can't make 2.6 behave like 2.5"
> > would have been a better answer.)
>
> > Failing that, how about something that explains why 2.6 behaves
> > differently than 2.5, and why one of them is better or more correct
> > than the other?
>
> > Personally, I think 2.6's is probably the more correct behavior.
> > Specifically, if the point of the -i command line option is to force
> > interactive mode after completion of the script (which in this case
> > completed with sys.exit), then it should go to interactive mode
> > regardless of whether the script terminates "normally" or not.  I
> > think 2.5's behavior of allowing interactive mode to be skipped is
> > against the spirit of -i.  Unless -i meant something different in 2.5.
>
> > Is there some kind of environment variable to set up to control this?
>
> > John
>
> I can understand the behavior from a '-i' point of view. My
> requirement is somewhat different. Consider a geometry tool that can
> be used to create objects, merge objects etc. I have python 'commands'
> for doing any of these operations and for saving the objects to a
> file. The user could write a file containing a set of commands (in
> python format) and load this file in the GUI. Optionally, one of the
> commands could be to exit in which case the GUI should shut down. I am
> using 'execfile' to execute the file, and this does not exit if the
> user has used sys.exit (or even if I expose a command called 'Exit'
> which calls sys.exit).
>
> May be I should not be using execfile but I am not sure what else I
> should use. The user-written file could contain loops and other
> constructs as well.
>
> -Krishnan

Hi,

I had been starting my application with -i option. I have removed this
now and made a few other changes and things work OK now.

Thanks to everyone who helped in this.

Regards,
Krishnan
-- 
http://mail.python.org/mailman/listinfo/python-list


question on namedtuple

2010-04-01 Thread hetchkay
Hi,
For purposes I don't want to go into here, I have the following code:
def handleObj(obj):
  if isinstance(obj, MyType):
 return obj.handle()
  elif isinstance(obj, (list, tuple, set)):
 return obj.__class__(map (handleObj, obj))
  elif isinstance(obj, dict):
 return obj.__class__((handleObj(k), handleObj(v)) for k, v in
obj.items())
  else:
 return obj

This works fine except if obj is a namedtuple. A namedtuple object has
different constructor signature from tuple:
>>> tuple([1,2])
(1,2)
>>> collections.namedtuple("sample", "a, b")([1, 2])
Traceback (most recent call last):
  File "CommandConsole", line 1, in 
TypeError: __new__() takes exactly 3 arguments (2 given)
>>> collections.namedtuple("sample", "a, b")(1, 2)
sample(a=1, b=2)

Is there any easy way of knowing that the obj is a namedtuple and not
a plain tuple [so that I could use obj.__class__(*map(handleObj, obj))
instead of obj.__class__(map(handleObj, obj)) ].

Thanks in advance for your help.

Krishnan
-- 
http://mail.python.org/mailman/listinfo/python-list