setting variables in the local namespace

C

Chris Withers

Hi All,

Say I have a piece of code like this:

mname = model.__name__
fname = mname+'_order'
value = request.GET.get('order')
if value:
request.session[fname]=value
else:
value = request.session.get(
fname,
model.default_name
)

Now, if I want to do *exactly* the same thing with a variable named
'sort', I have to copy and paste the above code or do something hacky
like have a dict called "vars" and manipulate that, or factor the above
into a function and take the hit on the extra function call...

What I'd be looking for is something like:

locals()[name]=value

....or, say:

setattr(<somethingspecial>,name,value)

Now, I got horribly flamed for daring to be so heretical as to suggest
this might be a desirable thing in #python, so I thought I'd ask here
before trying to take this to python-dev or writing a PEP:

- what is so wrong with wanting to set a variable in the local namespace
based on a name stored in a variable?

- have I missed something that lets me do this already?

cheers,

Chris
 
M

Mick Krippendorf

Hello.

Chris said:
mname = model.__name__
fname = mname+'_order'
value = request.GET.get('order')
if value:
request.session[fname]=value
else:
value = request.session.get(
fname,
model.default_name
)

Now, if I want to do *exactly* the same thing with a variable named
'sort',

I don't really understand what you mean by "*exactly* the same".
request.GET.get('sort') ?
or
request.session[fname] = locals()['sort']
maybe? or sth else?
I have to copy and paste the above code or do something hacky
like have a dict called "vars" and manipulate that, or factor the above
into a function and take the hit on the extra function call...

From the "request.session" stuff I conclude you're writing a webapp.
Compared to all the other time consuming things involved, I think,
another function call is negligible.
What I'd be looking for is something like:

locals()[name]=value

That will probably do what you want, and if that is a good idea depends
not on the pythonicity of it per se, but on the context in which you use
it, which I, as mentioned earlier, don't quite understand.
- what is so wrong with wanting to set a variable in the local namespace
based on a name stored in a variable?

What's your use case, I ask?
- have I missed something that lets me do this already?

Yes, and, uh, yes. "locals()['foo'] = bar" works in that it does the
same thing as "foo = bar". So why don't you write that instead?

Mick.
 
C

Carl Banks

Hi All,

Say I have a piece of code like this:

         mname = model.__name__
         fname = mname+'_order'
         value = request.GET.get('order')
         if value:
             request.session[fname]=value
         else:
             value = request.session.get(
                 fname,
                 model.default_name
                 )

Now, if I want to do *exactly* the same thing with a variable named
'sort', I have to copy and paste the above code or do something hacky
like have a dict called "vars" and manipulate that, or factor the above
into a function and take the hit on the extra function call...

Just a bit of perspective:

Once you are at the point of worrying about taking a hit on an extra
function call, a lot of the other things that are normally bad ideas
(like cutting and pasting a lot of code) aren't considered "bad"
anymore. At least, not if you have good reason to worry about the
overhead of a function call.

The right way to this kind of thing, almost always, is to factor this
code into a function.

What I'd be looking for is something like:

locals()[name]=value

...or, say:

setattr(<somethingspecial>,name,value)

Now, I got horribly flamed for daring to be so heretical as to suggest
this might be a desirable thing in #python, so I thought I'd ask here
before trying to take this to python-dev or writing a PEP:

- what is so wrong with wanting to set a variable in the local namespace
based on a name stored in a variable?

My opinion: It's not necessarily a bad thing to do per se, but
whenever people think they want to do this, very often they are
approaching the problem the wrong way, especially when done with
locals. (There are more valid reasons to do it a global level.)

One thing I've noticed is that often people only really need the
convenient local names for testing. Example: I once set up an object
that had dynamically-assigned attributes that it read from a file.
(So you'd write "x = load_values(filename)", and it would return an
object with attributes determined from the data in the file.) I did
it that way because I got irritated typing x["attr"] all the time, and
thought it'd be better to type x.attr. But, when I got around to
actually using x, I found that I was always accessing the attributes
dynamically with getattr and setattr. Whoops, wasn't that useful
after all.

There are some cases when dynamically settable locals really might be
helpful. I'm not saying it's heretical to want it. But on the whole
I'd rather not see it allowed. I'd expect it to be overused, and when
it is used readability can take a severe hit.

- have I missed something that lets me do this already?

No.

However, one thing that might work in your case would be to then pass
a dictionary as keyword arguments into a function that defines the
locals you need.

u['value'] = 1
u['sort'] = 2
u['key'] = 3

def something(value,sort,key):
return value + sort + key # look they're locals now

something(**u)


Carl Banks
 
M

Mel

Chris said:
- what is so wrong with wanting to set a variable in the local namespace
based on a name stored in a variable?

What's wrong is that no other statement using the local name space can know
what that name might be. It's a documented fact that changing the locals()
dictionary doesn't feed back to the users of the namespace:

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information..... foo=0
.... globals()['foo'] = 'bar'
.... return foo
.... 0

For the reasons Gabriel gave outside the thread.

You can actually assign into a local namespace using exec:

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information..... exec (s)
.... return a
.... 4

But look at the dependency you'll create between the function's code and the
incoming data stream:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in g
NameError: name 'a' is not defined


Once you start naming local variables at run-time, you pretty much commit to
writing the entire function at run-time. Better to use a dictionary.

Mel.
 
C

Carl Banks

Yes, and, uh, yes. "locals()['foo'] = bar" works in that it does the
same thing as "foo = bar". So why don't you write that instead?

Lemme guess.

You tried this at the interactive prompt and concluded it worked in
general, right?

Even though when we speak of local variables, we usually are referring
to local variables inside a function, you didn't actually test whether
locals() works in a function, did you?

Because if you had you would have seen it doesn't work.


One of these days we're going to have a thread like this where no one
makes this mistake. Don't know when, but one day it will happen.


Carl Banks
 
D

Dave Angel

Mick said:
<snip>

Yes, and, uh, yes. "locals()['foo'] = bar" works in that it does the
same thing as "foo = bar". So why don't you write that instead?

Mick.
I wouldn't expect it to do the same thing at all, and it doesn't, at
least not in Python 2.6.2. It may store the "bar" somewhere, but not in
anything resembling a local variable.


bar = 42

def mytestfunc():
stuff = 9
locals()['stuff'] = bar
print locals()['stuff']
print stuff

mytestfunc()

prints 9, twice. No sign of the 42 value.


DaveA
 
P

Peter Pearson

On Tue, 13 Oct 2009 17:05:03 +0100, Chris Withers wrote:
[snip]
- what is so wrong with wanting to set a variable in the local namespace
based on a name stored in a variable?

I'm not sure it's "so wrong" that one should never, ever do
it, but it *does* blur the boundary between the program and
the data on which the program operates. Also, variable
names are customarily for the convenience of programmers, and
have often (e.g., compiled languages) disappeared by
run-time; so run-time references to variable names seem to
puncture the "what's for programmers" / "what's for the hardware"
distinction.

It strikes me much as the question, "What's so wrong with having
a soda straw going from the driver's seat to the gas tank?" Curious
question. Go ahead! Odd that it should seem desirable, though.
I hope the smart guys on this group can do a more precise job of
expressing this.
 
M

Mick Krippendorf

Carl said:
Lemme guess.

You tried this at the interactive prompt and concluded it worked in
general, right?

Yes. Thank you for enlighten me.
One of these days we're going to have a thread like this where no one
makes this mistake. Don't know when, but one day it will happen.

But at least it will not be my mistake anymore.

Mick.
 
C

Carl Banks

Yes. Thank you for enlighten me.


But at least it will not be my mistake anymore.

One by one, baby. It just amazes me so many people don't think to
check inside a function, especially when we normally think of local
variables as being local to a function. If I wasn't familiar with
locals(), it probably wouldn't even occur to me to try using locals()
at the top level. I'd expect it to throw an exception like "No locals
at global level".


Carl Banks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top