Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #10602 > unrolled thread
| Started by | Laszlo Nagy <gandalf@shopzeus.com> |
|---|---|
| First post | 2011-07-31 00:18 +0200 |
| Last post | 2011-07-31 12:21 +0200 |
| Articles | 3 — 2 participants |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: eval, exec and execfile dilemma Laszlo Nagy <gandalf@shopzeus.com> - 2011-07-31 00:18 +0200
Re: eval, exec and execfile dilemma Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-07-31 09:31 +1000
Re: eval, exec and execfile dilemma Laszlo Nagy <gandalf@shopzeus.com> - 2011-07-31 12:21 +0200
| From | Laszlo Nagy <gandalf@shopzeus.com> |
|---|---|
| Date | 2011-07-31 00:18 +0200 |
| Subject | Re: eval, exec and execfile dilemma |
| Message-ID | <mailman.1677.1312064338.1164.python-list@python.org> |
>> UnboundLocalError: local variable 'bar' referenced before assignment
>
> This works, though (at least it does on 2.7):
>
> --> exec "def foo():\n\tglobal bar\n\tbar+=1\n\treturn 1\n"
> --> bar = 9
> --> foo()
> 1
> --> bar
> 10
>
> Laszlo, why do you think you can't use exec?
I'm sorry, first I was not aware of the "in globals locals" part.
Then I also got an UnboundLocalError. Then I also figured out that I can
use "global bar", but I did not want to. Reason: 100 functions/second
installed to global namespace doesn't sound well. However, now I
discovered the locals parameter, and I figured out that I can force the
compiler to treat the name of the function to be a local name. I do this
by reserving its name in locals. Then the compiler has no choice but to
place it in the local namespace:
locals = {'_f_':None}
globals ={} # More specialized version in my program...
exec "def _f_(a):\n\treturn a+1\n\n" in globals,locals
print locals['_f_'](4) # prints '5'
This is good because it is not interfering with module level globals(),
nor the local namespace. Also good because I can restrict what is
visible from inside the function.
Thank you for your help.
Best,
Laszlo
[toc] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-07-31 09:31 +1000 |
| Message-ID | <4e349443$0$29975$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #10602 |
Laszlo Nagy wrote:
> 100 functions/second
> installed to global namespace doesn't sound well.
What on earth are you doing needing to use exec to create hundreds of
functions??????
Have you considered not using exec at all, and using a good old-fashioned
factory function and closures?
def factory(x):
def inner(param):
return param + x
return inner
plusone = factory(1)
plustwo = factory(2)
I'm betting that this will be much faster than exec, and much more readable.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Laszlo Nagy <gandalf@shopzeus.com> |
|---|---|
| Date | 2011-07-31 12:21 +0200 |
| Message-ID | <mailman.1691.1312107740.1164.python-list@python.org> |
| In reply to | #10604 |
>> 100 functions/second
>> installed to global namespace doesn't sound well.
> What on earth are you doing needing to use exec to create hundreds of
> functions??????
:-)
> Have you considered not using exec at all, and using a good old-fashioned
> factory function and closures?
>
> def factory(x):
> def inner(param):
> return param + x
> return inner
>
> plusone = factory(1)
> plustwo = factory(2)
>
>
> I'm betting that this will be much faster than exec, and much more readable.
I'm working on a program that creates pivot tables from
multi-dimensional databases. The user is able to give expressions in a
tiny language. These expressions are then converted to Python source
code, and compiled into functions.
The generated function is called with several different numpy arrays. In
most cases, there are only a few functions are created (e.g. when the
user changes the expression) and they are called many times. But
sometimes (for example, when creating charts from the data) I have to
generate a separate function for every fact set in the database. When
there are many data series with lots of data in the graph, some 100
functions needs to be generated very fast.
This cannot be done using factory functions, because the function code
depends on the user's expression. It COULD be done in a different way:
parsing the user's expression into an abstract syntax tree and then
provide methods in the AST to evaluate itself. But this approach would
use too many python method calls. By generating the function source
code, I can reduce the number of Python method calls needed from several
thousand to ten or so. In most cases, the user will enter an expression
that will produce a lambda function (eval+lambda). But with more
elaborate expressions, I cannot efficiently convert it to a lambda
expression.
Of course the user can always write the expression in pure Python source
code, but there are obvious problems with that...
Best,
Laszlo
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web