Re: Question about locals()

Discussion in 'Python' started by John O'Hagan, May 19, 2009.

  1. John O'Hagan

    John O'Hagan Guest

    On Tue, 19 May 2009, Gökhan SEVER wrote:
    > Hello,
    >
    > Could you please explain why locals() allow me to create variables that are
    > not legal in Python syntax. Example: locals()['1abc'] = 55. Calling of 1abc
    > results with a syntax error. Shouldn't it be better to raise an error
    > during the variable creation time?
    >


    The docs warn against modifying locals() because for one thing, the
    interpreter may not know about the changes you make.

    You can add any item to the locals() dictionary without causing an error, but
    that doesn't necessarily mean you have created a legal object and named it.

    But admittedly that doesn't actually answer your question. :)

    Regards,

    John
     
    John O'Hagan, May 19, 2009
    #1
    1. Advertising

  2. Sorry for breaking threading, the original post is not being carried by
    my ISP.


    On Tue, 19 May 2009, Gökhan SEVER wrote:
    > Hello,
    >
    > Could you please explain why locals() allow me to create variables that
    > are not legal in Python syntax. Example: locals()['1abc'] = 55. Calling
    > of 1abc results with a syntax error. Shouldn't it be better to raise an
    > error during the variable creation time?


    No, because it isn't an error to use '1abc' as a dictionary key.

    "locals()['1abc'] = 55" does not create a variable. It creates an object
    55, a string '1abc', and uses that string as the key in a dict with 55 as
    the value.

    "locals()['abc'] = 55" does not create a variable either. It does exactly
    the same thing as above, except that in this case 'abc' happens to be a
    valid identifier.

    "abc = 55" also does not create a variable. What it does is exactly the
    same as the above, except that the dictionary key is forced to be a valid
    identifier by the parser (or perhaps the lexer): the parser won't accept
    1abc as a valid identifier, so you can't execute "1abc = 55".

    (Almost... there's actually a slight complication, namely that making
    changes to locals() inside a function does not work.)

    Python's programming model is based on namespaces, and namespaces are
    implemented as dictionaries: so-called "variables" are key/value pairs
    inside a dictionary. Just because a dictionary is used as a namespace
    doesn't stop it from being used as a dictionary: you can add any keys/
    values which would otherwise be valid. It's still a dictionary, just like
    any other dictionary.

    >>> globals()[45] = None
    >>> globals()

    {'__builtins__': <module '__builtin__' (built-in)>, 45: None, '__name__':
    '__main__', '__doc__': None}


    As for *why* this is done this way, the answer is simplicity of
    implementation. Dictionaries don't need to care about what counts as a
    valid identifier. Only the lexer/parser needs to care.


    --
    Steven
     
    Steven D'Aprano, May 19, 2009
    #2
    1. Advertising

  3. En Tue, 19 May 2009 14:06:04 -0300, Gökhan SEVER <>
    escribió:

    > I will make double sure myself while using locals() to end up with valid
    > identifiers.


    I would ask myself why I'm using locals() in the first place.


    --
    Gabriel Genellina
     
    Gabriel Genellina, May 22, 2009
    #3
  4. On Fri, May 22, 2009 at 10:27 AM, Gökhan SEVER <> wrote:
    ....
    > serialc = np.loadtxt(sys.argv[1], skiprows=skiprows).T
    > for i in range(20):
    >     locals()['serialc_bin' + str(i+1)] = serialc[i+4]
    >
    > I don't know easier way than using locals() to construct variable-like
    > identities in my program.


    I don't either. I also don't know why you feel you need to construct
    variable-like identities.
    Why is:
    serialc_bin1
    better than
    serialc_bin[0]
    or, for that matter,
    serialc[4]

    ???
     
    David Robinow, May 22, 2009
    #4
  5. Top-posting corrected.

    On Fri, 2009-05-22 at 10:00 -0500, Gökhan SEVER wrote:

    > On Fri, May 22, 2009 at 9:43 AM, David Robinow <>
    > wrote:
    > On Fri, May 22, 2009 at 10:27 AM, Gökhan SEVER
    > <> wrote:
    > ...
    > > serialc = np.loadtxt(sys.argv[1], skiprows=skiprows).T
    > > for i in range(20):
    > > locals()['serialc_bin' + str(i+1)] = serialc[i+4]
    > >
    > > I don't know easier way than using locals() to construct

    > variable-like
    > > identities in my program.

    >
    >
    > I don't either. I also don't know why you feel you need to
    > construct
    > variable-like identities.
    > Why is:
    > serialc_bin1
    > better than
    > serialc_bin[0]
    > or, for that matter,
    > serialc[4]
    >
    > ???
    >
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >


    > Because in this case serialc is an numpy array. Since loadtxt returns
    > a numpy-array. Furthermore
    >
    > locals()['serialc_bin' + str(i+1)] creates a dictionary key (that's
    > what I use the term "variable-like") serialc_bin1, serialc_bin2, ...
    > not serialc_bin[0] with indexes.
    >
    >
    > Gökhan
    >
    >


    I'm not sure why dictionary keys are better than indexes in your
    example, especially as they're being created by coercing integers to
    strings. However, that's your business. But why not just create your
    own dictionary. Then you can pass the results around easily as a group
    or one at a time, and you don't have to mess in locals() (which isn't
    supposed to be messed in). It also gives you more flexibility as to how
    you name your entries:

    d = {}

    You can use the same indexes you're using now:

    d['serialc_bin' + str(i+1)] = serialc[i+4]

    or you can keep the integerness of i by using tuples as keys (thus
    preserving sort order across your keys):

    d[('serialc_bin', i+1)] = serialc[i+4]

    or you can use the integer as a key by itself (yes! It looks like
    you're accessing a list, but it's actually a dict with integer keys):

    d[i+1] = serialc[i+4]

    Or you can use a dict with a more descriptive name and the last above
    solution gains the readability of your initial solution:

    serialc_bin = {}
    serialc_bin[i+1] = serialc[i+4]

    Finally, if there's more you want to do with these numbers, you can
    create a class to hold them. Then as you need to, you can add methods
    to it to implement the behavior you're looking for.

    class MyCollection(object):
    """Untested code"""

    def __init__(self):
    self._store = {}

    def __getitem__(self, item):
    return self._store[item]

    def __setitem__(self, item, value):
    self._store[item] = value

    def __delitem__(self, item):
    del(self._store[item])

    def sum(self):
    total = 0
    for value in self._store.values():
    total += value
    return value

    serialc_bin = MyCollection()
    for i, value in enumerate(serialc):
    serialc_bin[i+1] = value
    print serialc_bin.sum()

    Any one of these seems like a better idea to me than trying to pollute
    your local namespace with an unknown number of variables. You have a
    collection of objects. It makes sense to store them in one of python's
    collection types, or create an object of your own to store them.

    Cheers,
    Cliff
     
    J. Cliff Dyer, May 22, 2009
    #5
    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. Aaron Ackerman
    Replies:
    5
    Views:
    417
    Chris Dunaway
    Oct 13, 2003
  2. dgk
    Replies:
    2
    Views:
    406
  3. Giles Brown

    Question about "exec in globals, locals"

    Giles Brown, Jul 4, 2003, in forum: Python
    Replies:
    2
    Views:
    361
    Adrien Di Mascio
    Jul 4, 2003
  4. Faisal Alquaddoomi

    Globals, Locals Dictionaries + Callbacks Question

    Faisal Alquaddoomi, Dec 21, 2005, in forum: Python
    Replies:
    3
    Views:
    366
    Steve Holden
    Dec 22, 2005
  5. Ed Anuff
    Replies:
    2
    Views:
    211
    Ed Anuff
    Sep 14, 2009
Loading...

Share This Page