Re: updating local()

2005-10-14 Thread Bengt Richter
On Thu, 06 Oct 2005 07:15:12 -0700, Robert Kern <[EMAIL PROTECTED]> wrote:

>Flavio wrote:
>> Ok, its not thousands, but more like dozens of variables...
>> I am reading a large form from the web which returns a lot of values.
>> (I am Using cherrypy)
>> 
>> I know I could pass these variables around as:
>> 
>> def some_function(**variables):
>> ...
>> 
>> some_function(**variables)
>> 
>> but its a pain in the neck to have to refer to them as
>> variables['whatever']...
>> 
>> dont you think? 
>
>Use a Bunch.
>
>class Bunch(dict):
>def __init__(self, *args, **kwds):
>dict.__init__(self, *args, **kwds)
>self.__dict__ = self
>
>--
Or use a version-sensitive byte-code hack to set some preset locals before 
executing,
either with one-time presets via normal decorator, e.g.,

 >>> from ut.presets import presets
 >>> @presets(x=111, y=222, z='zee')
 ... def foo():
 ... return locals()
 ...
 >>> foo()
 {'y': 222, 'x': 111, 'z': 'zee'}

Or the same, just using a predefined dict instead of the keyword format:

 >>> e = {'a':0, 'b':1}
 >>> @presets(**e)
 ... def foo():
 ... return locals()
 ...
 >>> foo()
 {'a': 0, 'b': 1}

What happened to foo viat the decoration:
 >>> import dis
 >>> dis.dis(foo)
   1   0 LOAD_CONST   1 ((0, 1))
   3 UNPACK_SEQUENCE  2
   6 STORE_FAST   0 (a)
   9 STORE_FAST   1 (b)

   3  12 LOAD_GLOBAL  0 (locals)
  15 CALL_FUNCTION0
  18 RETURN_VALUE

To mess with the same base function with different presets more dynamically,
use the explicit way of calling the decorator:

The base function:

 >>> def bar(x, y=123):
 ...return locals()
 ...

decorate and invoke on the fly with particular presets:

 >>> presets(**e)(bar)('exx')
 {'a': 0, 'y': 123, 'b': 1, 'x': 'exx'}

The keyword way:
 >>> presets(hey='there')(bar)('exx')
 {'y': 123, 'x': 'exx', 'hey': 'there'}

BTW, @presets does not change the signature of the function whose selected 
locals
are being preset from the decoration-time-generated constant, e.g.,

 >>> presets(hey='there')(bar)()
 Traceback (most recent call last):
   File "", line 1, in ?
 TypeError: bar() takes at least 1 argument (0 given)
 >>> presets(hey='there')(bar)('exx', 'wye')
 {'y': 'wye', 'x': 'exx', 'hey': 'there'}
 >>> presets(hey='there')(bar)('exx', 'wye', 'zee')
 Traceback (most recent call last):
   File "", line 1, in ?
 TypeError: bar() takes at most 2 arguments (3 given)

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


Re: updating local()

2005-10-06 Thread Grant Edwards
On 2005-10-06, Flavio <[EMAIL PROTECTED]> wrote:
> Ok,
>
> I got it!
>
> Its vey insecure, and it is not guaranteed to work. Fine.
>
> Now what would you do if you wanted to pass a lot of variables (like a
> thousand) to a function and did not wanted the declare them in the
> function header?

Pass them in a dictionary or tuple or list or object with
attributes.

-- 
Grant Edwards   grante Yow!  Am I SHOPLIFTING?
  at   
   visi.com
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: updating local()

2005-10-06 Thread El Pitonero
Flavio wrote:
> I wish all my problems involved just a couple of variables, but
> unfortunately the real interesting problems tend to be complex...
>
> def fun(**kw):
> a = 100
> for k,v in kw.items():
> exec('%s = %s'%(k,v))
> print locals()
>
>
> >>> fun(**{'a':1,'b':2})
> {'a': 1, 'k': 'b', 'b': 2, 'kw': {'a': 1, 'b': 2}, 'v': 2}
>
> any better Ideas?

Actually, your solution is not bad. Some potential problems are: (1)
unintentional name collisions with other variables, including
globals/builtins, (2) it's easy to unpack variables into locals(), but
not easy to pack them back, since locals() are often contaminated with
extra auxiliary variables.

Your problem happens often in the field of math formulas/equations.

I remember similar problem happens in C++, too. When one has a function
with a long list of parameters, in C++ one may find oneself updating
the funtion header/prototype all the time, which is very tiresome and
error-prone.

When you have complicated list of arguments to pass, it's better to put
them into a structure/object. This way, the function header/prototype
will remain the same, and you only need to change the declaration of
the object.

The parameter object(s) could be called:

- request and response, if input and output are separated
- param
- workspace, session, etc.

so, your function call would look like

class Param: pass
...
def f(p):
result = p.x + p.y
return result
...
p=Param()
p.x = 3
p.y = 4
result = f(p)

Now, you may not like the extra dots in the line:

result = p.x + p.y

My experience is: it's not that bad to have names with extra dots. I
know it's annoying, but not a total disaster. Plus, once you start to
use OOP, it makes your code more organized. It has its benefits. For
instance, very often your models/formulas have several versions. Using
OOP's class hierarchy inheritance mechanism allows you to try out
different versions or different ideas much more easily, and you can
roll back the changes more easily, too (instead of commenting out code
lines all over places.) If you do decide to go the route of OOP, the
lines:

p.x = 3
p.y = 4
p.z = 5

can be replaced by something like:

calculation_engine.set(x=3, y=4)
calculation_engine.set(z=5)

--

The longer answer is: if you need complex formula evaluations, Python
is probably not the language to use. For speed and memory usage issues,
C++ is probably what you need. You can hookup your C++ program to
Python in various ways, but packing/unpacking variables seems
unavoidable. And even in C++ (where object attributes don't have the
dots inside the object's own methods), I still often end up using a lot
of dotted names for attributes from other objects.

If the problem is complex, then it's complex. I know you have your
equations, but you have to decide for yourself: is it better to do all
the packing/unpacking, or is it better to change your equations to use
the dotted names? There is no right or wrong answer, it all depends on
your particular situation.

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


Re: updating local()

2005-10-06 Thread Robert Kern
Flavio wrote:
> Ok, its not thousands, but more like dozens of variables...
> I am reading a large form from the web which returns a lot of values.
> (I am Using cherrypy)
> 
> I know I could pass these variables around as:
> 
> def some_function(**variables):
> ...
> 
> some_function(**variables)
> 
> but its a pain in the neck to have to refer to them as
> variables['whatever']...
> 
> dont you think? 

Use a Bunch.

class Bunch(dict):
def __init__(self, *args, **kwds):
dict.__init__(self, *args, **kwds)
self.__dict__ = self

-- 
Robert Kern
[EMAIL PROTECTED]

"In the fields of hell where the grass grows high
 Are the graves of dreams allowed to die."
  -- Richard Harter

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


Re: updating local()

2005-10-06 Thread Simon Brunning
On 6 Oct 2005 07:04:08 -0700, Flavio <[EMAIL PROTECTED]> wrote:
> I know I could pass these variables around as:
>
> def some_function(**variables):
> ...
>
> some_function(**variables)
>
> but its a pain in the neck to have to refer to them as
> variables['whatever']...
>
> dont you think?

Err, no, not really. ;-)

If you'd prfefer to access them like this:

variables.whatever

Check out the Bunch class here -
.

--
Cheers,
Simon B,
[EMAIL PROTECTED],
http://www.brunningonline.net/simon/blog/
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: updating local()

2005-10-06 Thread Flavio
Ok, its not thousands, but more like dozens of variables...
I am reading a large form from the web which returns a lot of values.
(I am Using cherrypy)

I know I could pass these variables around as:

def some_function(**variables):
...

some_function(**variables)

but its a pain in the neck to have to refer to them as
variables['whatever']...

dont you think? 

Flavio

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


Re: updating local()

2005-10-06 Thread Flavio
I wish all my problems involved just a couple of variables, but
unfortunately the real interesting problems tend to be complex...

As a last resort this problem could be solved by something like this:

def fun(**kw):
a = 100
for k,v in kw.items():
exec('%s = %s'%(k,v))
print locals()


>>> fun(**{'a':1,'b':2})
{'a': 1, 'k': 'b', 'b': 2, 'kw': {'a': 1, 'b': 2}, 'v': 2}

But that would be utterly stupid! So much for not being able to write
to locals()

any better Ideas?

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


Re: updating local()

2005-10-06 Thread Steve Holden
Richard Brodie wrote:
> "Flavio" <[EMAIL PROTECTED]> wrote in message
> news:[EMAIL PROTECTED]
> 
> 
>>Now what would you do if you wanted to pass a lot of variables (like a
>>thousand) to a function and did not wanted the declare them in the
>>function header?
> 
> 
> I'd lie down until I felt better.
> 
> 
Or alternatively put them in a 1,000-element list. Just as a matter of 
interest, what on *earth* is the use case for a function with a thousand 
arguments?

regards
  Steve
-- 
Steve Holden   +44 150 684 7255  +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006  www.python.org/pycon/

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


Re: updating local()

2005-10-06 Thread Diez B. Roggisch
Flavio wrote:
> Ok,
> 
> I got it!
> 
> Its vey insecure, and it is not guaranteed to work. Fine.
> 
> Now what would you do if you wanted to pass a lot of variables (like a
> thousand) to a function and did not wanted the declare them in the
> function header?

use a dict or list? This is almost certainly a design smell - and a 
pretty strong one, too.. Nobody is using so many variables and actually 
typing them - so there certainly is some naming scheme that could be 
used to access the values from a dict.

Or, to put it differently: show us the code that uses thousands of 
variables, and we show you how to improve that.

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


Re: updating local()

2005-10-06 Thread Simon Brunning
On 6 Oct 2005 05:55:14 -0700, Flavio <[EMAIL PROTECTED]> wrote:
> Now what would you do if you wanted to pass a lot of variables (like a
> thousand) to a function and did not wanted the declare them in the
> function header?

I'd think twice. If on reflection I decided I really wanted to do it,
I'd pass them all in a dictionary.

--
Cheers,
Simon B,
[EMAIL PROTECTED],
http://www.brunningonline.net/simon/blog/
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: updating local()

2005-10-06 Thread Richard Brodie

"Flavio" <[EMAIL PROTECTED]> wrote in message
news:[EMAIL PROTECTED]

> Now what would you do if you wanted to pass a lot of variables (like a
> thousand) to a function and did not wanted the declare them in the
> function header?

I'd lie down until I felt better.


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


Re: updating local()

2005-10-06 Thread Flavio
Ok,

I got it!

Its vey insecure, and it is not guaranteed to work. Fine.

Now what would you do if you wanted to pass a lot of variables (like a
thousand) to a function and did not wanted the declare them in the
function header?

Flávio

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


Re: updating local()

2005-10-05 Thread Sybren Stuvel
Jp Calderone enlightened us with:
> If I can call functions in your process space, I've already taken
> over your whole program.

That's true for standalone programs, but not for things like web
applications, RPC calls etc.

Sybren
-- 
The problem with the world is stupidity. Not saying there should be a
capital punishment for stupidity, but why don't we just take the
safety labels off of everything and let the problem solve itself? 
 Frank Zappa
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: updating local()

2005-10-05 Thread jepler
I'm surprised you found any example of 'locals().update' that worked.
Here's one that doesn't work:
def f(y):
locals().update({'x': y})
return x

print f(3)  # prints 3?

Jeff


pgpLVe48NBWmT.pgp
Description: PGP signature
-- 
http://mail.python.org/mailman/listinfo/python-list

Re: updating local()

2005-10-05 Thread Jp Calderone


On Wed, 5 Oct 2005 18:47:06 +0200, Sybren Stuvel <[EMAIL PROTECTED]> wrote:
>Flavio enlightened us with:
>> Can anyone tell me why, if the following code works, I should not do
>> this?
>>
>> def fun(a=1,b=2,**args):
>>
>>  print 'locals:',locals()
>>  locals().update(args)
>>  print locals()
>
>Because it's very, very, very insecure. What would happen if someone
>found a way to call that function? It could replace any name in the
>locals dictionary, including functions from __builtins__. In other
>words: probably the whole program could be taken over by other code by
>just one call to that function.
>

If I can call functions in your process space, I've already taken over your 
whole program.

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


Re: updating local()

2005-10-05 Thread Duncan Booth
Flavio wrote:
> Can anyone tell me why, if the following code works, I should not do
> this?
> 
> #
> # Extending Local namespace
> #
> 
> def fun(a=1,b=2,**args):
> 
>  print 'locals:',locals()
>  locals().update(args)
>  print locals()
> 
> e = {'s':3,'e':4}
> fun(k=10,v=32,**e)
> 
Because if all you want is to update a dictionary you might as well use 
another dictionary which isn't locals(). If what you want is to update the 
local variables, that won't work:

>>> def fun(a=1,b=2,**args):
s = 1
print 'locals:',locals()
locals().update(args)
print locals()
print s, e


>>> e = {'s':3,'e':4}
>>> fun(k=10,v=32,**e)
locals: {'a': 1, 's': 1, 'args': {'s': 3, 'e': 4, 'k': 10, 'v': 32}, 'b': 
2}
{'a': 1, 'b': 2, 'e': 4, 'k': 10, 'args': {'s': 3, 'e': 4, 'k': 10, 'v': 
32}, 's': 1, 'v': 32}
1 {'s': 3, 'e': 4}
>>> 

Note that k, v, and e are added to the locals dictionary, but real local 
variables such as 's' are not updated. Also you cannot access k, v, and e 
as local variables within the function, if you try you get the global 
variables (if they exist).

Also, this behaviour is undefined. Different versions of Python will behave 
differently, and even minor code changes can change the behaviour. With 
this version, 's' still doesn't update, but we can now access the 'e' value 
as a variable:

>>> def fun(a=1,b=2,**args):
s = 1
print 'locals:',locals()
locals().update(args)
print locals()
exec "print 'hi'"
print s,e


>>> fun(k=10,v=32,**e)
locals: {'a': 1, 's': 1, 'args': {'s': 3, 'e': 4, 'k': 10, 'v': 32}, 'b': 
2}
{'a': 1, 'b': 2, 'e': 4, 'k': 10, 'args': {'s': 3, 'e': 4, 'k': 10, 'v': 
32}, 's': 1, 'v': 32}
hi
1 4
>>> 

Short answer: don't even think of trying to update locals().
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: updating local()

2005-10-05 Thread Fredrik Lundh
"Flavio" <[EMAIL PROTECTED]> wrote:

> Can anyone tell me why, if the following code works, I should not do
> this?

because it doesn't work:

#
# Extending Local namespace, now with Local namespace
#

def fun(a=1,b=2,**args):
k="K"
v="V"
print 'locals:',locals()
locals().update(args)
print locals()
print k
print v

e = {'s':3,'e':4}
fun(k=10,v=32,**e)


 



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


Re: updating local()

2005-10-05 Thread Sybren Stuvel
Flavio enlightened us with:
> Can anyone tell me why, if the following code works, I should not do
> this?
>
> def fun(a=1,b=2,**args):
>
>   print 'locals:',locals()
>   locals().update(args)
>   print locals()

Because it's very, very, very insecure. What would happen if someone
found a way to call that function? It could replace any name in the
locals dictionary, including functions from __builtins__. In other
words: probably the whole program could be taken over by other code by
just one call to that function.

Sybren
-- 
The problem with the world is stupidity. Not saying there should be a
capital punishment for stupidity, but why don't we just take the
safety labels off of everything and let the problem solve itself? 
 Frank Zappa
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: updating local()

2005-10-05 Thread Steve Holden
Flavio wrote:
> Hi,
> 
>  I heard time and again that you are not _supposed_ to update the
> locals dictionary.
> 
> Can anyone tell me why, if the following code works, I should not do
> this?
> 
> #
> # Extending Local namespace
> #
> 
> def fun(a=1,b=2,**args):
> 
>   print 'locals:',locals()
>   locals().update(args)
>   print locals()
> 
> e = {'s':3,'e':4}
> fun(k=10,v=32,**e)
> 
Because it depends on the current implementation and isn't guaranteeed 
to work in the future.

regards
  Steve
-- 
Steve Holden   +44 150 684 7255  +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006  www.python.org/pycon/

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


updating local()

2005-10-05 Thread Flavio
Hi,

 I heard time and again that you are not _supposed_ to update the
locals dictionary.

Can anyone tell me why, if the following code works, I should not do
this?

#
# Extending Local namespace
#

def fun(a=1,b=2,**args):

print 'locals:',locals()
locals().update(args)
print locals()

e = {'s':3,'e':4}
fun(k=10,v=32,**e)


thanks,

Flávio

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