Applying a function recursively
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
>
> 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()
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()
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()
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()
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
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
