User defined lexical scoping... can I do this?

Discussion in 'Python' started by porkfried, Sep 18, 2012.

  1. porkfried

    porkfried Guest

    I want to define a 'with' command that makes entries
    in dictionary available within the local scope, and
    stores new local variables into that dictionary. The
    original scope should be restored on exit, and called
    functions should not see anything special. Can I do this?

    my_dict = dict(a=1, b=2)
    with MyScope(my_dict):
    print "A", a, "B", b
    x = 3
    print my_dict["x"]
    print x # FAIL, unbound
    porkfried, Sep 18, 2012
    #1
    1. Advertising

  2. On 09/18/2012 10:10 PM, porkfried wrote:
    > I want to define a 'with' command that makes entries
    > in dictionary available within the local scope, and
    > stores new local variables into that dictionary. The
    > original scope should be restored on exit, and called
    > functions should not see anything special. Can I do this?


    No.*

    It is not possible to set locals by ways other than an assignment**, and
    it is certainly not possible to set locals in a scope other than the one
    you're in**.

    You should simply type out the dict's name. This is a lot clearer. If
    you want to minimize typing, you can give the variable a one-character name.

    Also, Python scope simply doesn't work like that. There is no block
    scope, only local (=function) scope, and global scope, with a dash of
    non-locals to spice things up a bit.

    >
    > my_dict = dict(a=1, b=2)
    > with MyScope(my_dict):
    > print "A", a, "B", b
    > x = 3
    > print my_dict["x"]
    > print x # FAIL, unbound
    >


    *You could set global variables, and remove them on exit, but this is
    ugly for a number of reasons: this could overwrite existing globals if
    you're not very careful, called functions would see these globals, and
    they would also be exposed to other threads.

    **I believe there is actually a way to edit a caller's locals, but this
    is not documented, not portable across Python implementations and
    versions, and you couldn't create new locals like this, so it'd be
    fairly pointless here
    Thomas Jollans, Sep 18, 2012
    #2
    1. Advertising

  3. porkfried

    Guest

    On Tuesday, September 18, 2012 4:10:32 PM UTC-4, porkfried wrote:
    > I want to define a 'with' command that makes entries
    >
    > in dictionary available within the local scope, and
    >
    > stores new local variables into that dictionary. The
    >
    > original scope should be restored on exit, and called
    >
    > functions should not see anything special. Can I do this?
    >
    >
    >
    > my_dict = dict(a=1, b=2)
    >
    > with MyScope(my_dict):
    >
    > print "A", a, "B", b
    >
    > x = 3
    >
    > print my_dict["x"]
    >
    > print x # FAIL, unbound


    Well there's wired stuff like this:

    In [1]: locals()["x"] = 5

    In [2]: print x
    5

    In [3]:

    but it didn't help me do what I wanted.
    , Sep 18, 2012
    #3
  4. On 09/18/2012 10:50 PM, wrote:
    > Well there's wired stuff like this:
    >
    > In [1]: locals()["x"] = 5
    >
    > In [2]: print x
    > 5
    >


    No, there isn't. Modifying the dictionary returned by locals() has no
    effect.

    >>> def f ():

    .... locals()["x"] = 1
    .... return x
    ....
    >>> f ()

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 3, in f
    NameError: global name 'x' is not defined
    >>>
    >>> locals()["x"] = 1
    >>> x

    1
    >>> #this works because

    .... locals() is globals()
    True
    >>>


    The exception is the case when local scope is identical to global scope.
    In this case, locals() has globals() semantics.
    Thomas Jollans, Sep 18, 2012
    #4
  5. On 18/09/2012 21:10, porkfried wrote:
    > I want to define a 'with' command that makes entries
    > in dictionary available within the local scope, and
    > stores new local variables into that dictionary. The
    > original scope should be restored on exit, and called
    > functions should not see anything special. Can I do this?
    >
    > my_dict = dict(a=1, b=2)
    > with MyScope(my_dict):
    > print "A", a, "B", b
    > x = 3
    > print my_dict["x"]
    > print x # FAIL, unbound
    >


    If you could state what you're trying to achieve rather than how you're
    trying to achieve it then perhaps people could give you a solution to
    your problem.

    --
    Cheers.

    Mark Lawrence.
    Mark Lawrence, Sep 19, 2012
    #5
  6. porkfried

    Terry Reedy Guest

    On 9/18/2012 5:51 PM, Thomas Jollans wrote:
    > On 09/18/2012 10:50 PM, wrote:
    >> Well there's wired stuff like this:
    >>
    >> In [1]: locals()["x"] = 5
    >>
    >> In [2]: print x
    >> 5
    >>

    >
    > No, there isn't. Modifying the dictionary returned by locals() has no
    > effect.


    Last time I tried it, it does within a class -- in cpython at least.
    That locals dict usually becomes the __dict__ of the class. But not to
    be depended on indefinitely and across implmentations.


    --
    Terry Jan Reedy
    Terry Reedy, Sep 19, 2012
    #6
  7. On Tue, 18 Sep 2012 21:38:19 -0400, Terry Reedy wrote:

    > On 9/18/2012 5:51 PM, Thomas Jollans wrote:
    >> On 09/18/2012 10:50 PM, wrote:
    >>> Well there's wired stuff like this:
    >>>
    >>> In [1]: locals()["x"] = 5
    >>>
    >>> In [2]: print x
    >>> 5
    >>>
    >>>

    >> No, there isn't. Modifying the dictionary returned by locals() has no
    >> effect.

    >
    > Last time I tried it, it does within a class -- in cpython at least.
    > That locals dict usually becomes the __dict__ of the class. But not to
    > be depended on indefinitely and across implmentations.


    Exactly. The behaviour of modifying the dict returned by locals() is not
    defined. For example, this is what happens under Python 2.6, Jython 2.5,
    and IronPython 2.6:

    steve@runes:~$ cat test.py

    a = b = 'global'
    def test():
    a = None
    locals()['a'] = 'local'
    locals()['b'] = 'local'
    print a, b

    test()

    steve@runes:~$ python test.py
    None global
    steve@runes:~$ jython test.py
    None global
    steve@runes:~$ ipy test.py
    local global


    Other Python implementations may do differently.



    --
    Steven
    Steven D'Aprano, Sep 19, 2012
    #7
    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. Matt Barnicle
    Replies:
    10
    Views:
    628
    Bruno Desthuilliers
    Dec 2, 2007
  2. Khookie

    C closures & lexical scoping

    Khookie, Dec 12, 2007, in forum: C Programming
    Replies:
    28
    Views:
    1,361
    cr88192
    Dec 15, 2007
  3. walterbyrd
    Replies:
    16
    Views:
    463
    Steven D'Aprano
    Dec 18, 2008
  4. Aronaxis, the Sourceror

    (?{..}) and lexical scoping issues.

    Aronaxis, the Sourceror, Jun 20, 2004, in forum: Perl Misc
    Replies:
    3
    Views:
    199
    Anno Siegel
    Jun 21, 2004
  5. Louis.

    Lexical scoping question.

    Louis., Feb 10, 2005, in forum: Perl Misc
    Replies:
    8
    Views:
    184
    Michael Powe
    Feb 11, 2005
Loading...

Share This Page