setting variables in the local namespace

Discussion in 'Python' started by Chris Withers, Oct 13, 2009.

  1. 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

    --
    Simplistix - Content Management, Batch Processing & Python Consulting
    - http://www.simplistix.co.uk
     
    Chris Withers, Oct 13, 2009
    #1
    1. Advertising

  2. Hello.

    Chris Withers schrieb:
    > 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.
     
    Mick Krippendorf, Oct 13, 2009
    #2
    1. Advertising

  3. Chris Withers

    Carl Banks Guest

    On Oct 13, 9:05 am, Chris Withers <> wrote:
    > 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
     
    Carl Banks, Oct 13, 2009
    #3
  4. Chris Withers

    Mel Guest

    Chris Withers wrote:

    > - 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.
    >>> def f():

    .... foo=0
    .... globals()['foo'] = 'bar'
    .... return foo
    ....
    >>> f()

    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.
    >>> def g(s):

    .... exec (s)
    .... return a
    ....
    >>> g('a=4')

    4

    But look at the dependency you'll create between the function's code and the
    incoming data stream:

    >>> g('b=5')

    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.
     
    Mel, Oct 13, 2009
    #4
  5. Chris Withers

    Carl Banks Guest

    On Oct 13, 9:39 am, Mick Krippendorf <> wrote:
    > 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
     
    Carl Banks, Oct 13, 2009
    #5
  6. Chris Withers

    Dave Angel Guest

    Mick Krippendorf wrote:
    > <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
     
    Dave Angel, Oct 13, 2009
    #6
  7. 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.

    --
    To email me, substitute nowhere->spamcop, invalid->net.
     
    Peter Pearson, Oct 13, 2009
    #7
  8. Carl Banks schrieb:
    > 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.
     
    Mick Krippendorf, Oct 13, 2009
    #8
  9. Chris Withers

    Carl Banks Guest

    On Oct 13, 12:23 pm, Mick Krippendorf <> wrote:
    > Carl Banks schrieb:
    >
    > > 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.


    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
     
    Carl Banks, Oct 13, 2009
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sullivan WxPyQtKinter
    Replies:
    10
    Views:
    669
    Antoon Pardon
    Nov 8, 2007
  2. Tammo Tjarks
    Replies:
    2
    Views:
    288
    Tammo Tjarks
    Sep 13, 2007
  3. ara howard

    setting local variables via eval

    ara howard, Mar 11, 2008, in forum: Ruby
    Replies:
    15
    Views:
    321
    Robert Dober
    Mar 12, 2008
  4. Martin DeMello

    setting local variables in a binding

    Martin DeMello, Oct 6, 2010, in forum: Ruby
    Replies:
    13
    Views:
    233
    Robert Klemme
    Oct 14, 2010
  5. Brian Candler
    Replies:
    2
    Views:
    787
    Brian Candler
    Oct 14, 2010
Loading...

Share This Page