473,396 Members | 1,827 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

updating local()

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

Oct 5 '05 #1
18 1943
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/

Oct 5 '05 #2
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
Oct 5 '05 #3
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().
Oct 5 '05 #4
"Flavio" <fc******@gmail.com> 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)
</F>

Oct 5 '05 #5
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

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFDRBXeJd01MZaTXX0RAru9AKCLn7jtxwCFBIn6+ztaly hoN1vT9wCfR6yZ
1HxA4j8rhl/RlsF4mDmPlI8=
=rjtz
-----END PGP SIGNATURE-----

Oct 5 '05 #6
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
Oct 6 '05 #7
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

Oct 6 '05 #8

"Flavio" <fc******@gmail.com> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
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.
Oct 6 '05 #9
On 6 Oct 2005 05:55:14 -0700, Flavio <fc******@gmail.com> 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,
si***@brunningonline.net,
http://www.brunningonline.net/simon/blog/
Oct 6 '05 #10
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
Oct 6 '05 #11
Richard Brodie wrote:
"Flavio" <fc******@gmail.com> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...

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/

Oct 6 '05 #12
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?

Oct 6 '05 #13
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

Oct 6 '05 #14
On 6 Oct 2005 07:04:08 -0700, Flavio <fc******@gmail.com> 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 -
<http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52308>.

--
Cheers,
Simon B,
si***@brunningonline.net,
http://www.brunningonline.net/simon/blog/
Oct 6 '05 #15
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
rk***@ucsd.edu

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

Oct 6 '05 #16
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.

Oct 6 '05 #17
On 2005-10-06, Flavio <fc******@gmail.com> 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
Oct 6 '05 #18
On Thu, 06 Oct 2005 07:15:12 -0700, Robert Kern <ro*********@gmail.com> 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_FUNCTION 0
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 "<stdin>", 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 "<stdin>", line 1, in ?
TypeError: bar() takes at most 2 arguments (3 given)

Regards,
Bengt Richter
Oct 15 '05 #19

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Hal Vaughan | last post by:
First, I am aware of both SwingUtilities.invokeLater(), and of using Thread to create a new thread.  These are part of the problem. I want to have something running in the background, while the...
2
by: Glen | last post by:
Being a new'ish user to both Linux and Python, I've been 'happily' learning Python (2.3) with Idle and Tkinter as installed with Mandrake 10. Thought I would try installing Python 2.4 (to...
5
by: junglist | last post by:
Hi guys, I've been trying to implement an editable datagrid and i have been succesful up to the point where i can update my datagrid row by row. However what used to happen was that once i updated...
7
by: James | last post by:
Hi Has anybody had any experience of ASP.Net performance counters not updating. In the performance monitor application when I try to add the groups ASP.NET and ASP.NET Applications the...
2
by: Neil | last post by:
I was wondering if anybody could shed some light on this scenario, maybe there is white paper somewhere ? I have a vb.net app that runs on a few machines storing data in a local access db, but...
14
by: el_sid | last post by:
Our developers have experienced a problem with updating Web References in Visual Studio.NET 2003. Normally, when a web service class (.asmx) is created, updating the Web Reference will...
4
by: rdemyan via AccessMonster.com | last post by:
My application is calculation intensive and the servers are agonizingly slow. Administrators of my application only update the backends once a month (twice a month max). So, my launching program...
3
by: John Morgan | last post by:
I have my first small SQl Server 2005 database developed on my local server and I have also its equivalent as an online database. I wish to update the local database (using and asp.net interface)...
9
by: AG | last post by:
Using VS2005 Pro. I just deployed a ASP.NET 2.0 website (not web application) with the option to make it updatable. VS deployed all aspx, ascx files, but not all image or html files. It also...
5
by: Bill Schanks | last post by:
I have a winform app (VB 2005) that allows users to export data to excel, make updates to the excel file and import the data from that Excel file and update the database. My question is: Is it...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.