scope, function, mutable

Discussion in 'Python' started by gusarer@gmail.com, Dec 4, 2012.

  1. Guest

    Hi,

    What is the appropriate definition for the following behavior in Python 2.7
    (see code below).
    Both functions have assignment in it (like "x = ") so I assume, that x is a
    local variable in both functions.
    Also I thought this rule doesn't depend on WHERE in this function we find
    the assignment.

    But in both functions x becomes local variable only AFTER assignment, so in
    f2 x[1] = 99 changes the global varialble (btw, x[3] = 99 doesn't).

    def f1(x):
    x = [44] + x[1:]
    x[1] = 99

    def f2(x):
    x[1] = 99
    x = [44] + x[1:]
    x[3] = 99

    t = [1,2,3,4,5,6,7]
    f1(t)
    print t # [1, 2, 3, 4, 5, 6, 7]
    t = [1,2,3,4,5,6,7]
    f2(t)
    print t # [1, 99, 3, 4, 5, 6, 7]

    Thank you.

    Roman Gusarev.
    , Dec 4, 2012
    #1
    1. Advertising

  2. On Tue, 04 Dec 2012 14:55:44 +0400, gusarer wrote:

    > What is the appropriate definition for the following behavior in Python
    > 2.7 (see code below).
    > Both functions have assignment in it (like "x = ") so I assume, that x
    > is a local variable in both functions.


    Well, yes, but that's not why x is local in this case. In this case, x is
    local because the name of the function parameter is "x", and function
    parameters are always local.



    > Also I thought this rule doesn't depend on WHERE in this function we
    > find the assignment.
    >
    > But in both functions x becomes local variable only AFTER assignment,


    Not so. Read on.

    > so
    > in f2 x[1] = 99 changes the global varialble (btw, x[3] = 99 doesn't).
    >
    > def f1(x):
    > x = [44] + x[1:]
    > x[1] = 99


    When you call f1(t), with t a global list, Python passes the list object
    to the function and binds it to name x. The function gets executed like
    this pseudo-code:

    # calling f1(t)
    pass object known as "t" to the function
    bind that object to the local name "x"
    create a new list: [44] + a slice of x
    bind this new list to name "x"
    modify in place item 1 of the new list known as "x"


    Notice that the only *modification* occurs after a new list is created
    and bound to the name "x", so the modification does not change the
    original, global, list.


    But now consider your other function:

    > def f2(x):
    > x[1] = 99
    > x = [44] + x[1:]
    > x[3] = 99


    In pseudo-code again:

    # calling f2(t)
    pass object known as "t" to the function
    bind that object to the local name "x"
    modify in place item 1 of the list known as "x",
    which is another name for the global list known as "t"
    create a new list: [44] + a slice of x
    bind this new list to name "x"
    modify in place item 3 of the new list known as "x"

    So in this case you have to in-place modifications. The first occurs
    while the name "x" still refers to the original list, and so it modifies
    the original list. The second occurs after the name "x" has been rebound
    to a new list, and so it doesn't change the original.



    --
    Steven
    Steven D'Aprano, Dec 4, 2012
    #2
    1. Advertising

  3. writes:

    > What is the appropriate definition for the following behavior in
    > Python 2.7 (see code below).
    >
    > Both functions have assignment in it (like "x = ") so I assume, that
    > x is a local variable in both functions.


    It's a local variable in both functions because it's a formal
    parameter in both. The assignments don't make any difference
    here. (And a statement like x[k] = ... never does.)

    > Also I thought this rule doesn't depend on WHERE in this function we
    > find the assignment.


    That's correct but not relevant here. It's relevant when the variable
    does not occur in the function's parameter list.

    > But in both functions x becomes local variable only AFTER
    > assignment, so in f2 x[1] = 99 changes the global varialble (btw,
    > x[3] = 99 doesn't).


    In both functions, x is local from the start. Its initial value is the
    same mutable object that is the value of the global variable t. The
    assignments x = [44] ... give it a new value, another mutable object,
    but x[k] = ... don't. The latter make a change in the old value which
    is still the value of the globale variable t.

    > def f1(x):
    > x = [44] + x[1:]
    > x[1] = 99
    >
    > def f2(x):
    > x[1] = 99
    > x = [44] + x[1:]
    > x[3] = 99
    >
    > t = [1,2,3,4,5,6,7]
    > f1(t)
    > print t # [1, 2, 3, 4, 5, 6, 7]
    > t = [1,2,3,4,5,6,7]
    > f2(t)
    > print t # [1, 99, 3, 4, 5, 6, 7]


    You might want to consider something like the following, because the
    point really has everything to do with the fact that mutable objects
    are not copied when they are passed to functions, assigned to
    variables, or stored somewhere like a list, and little to do with
    global vs local (other than there being different variables with the
    same name).

    t = [1,2,3]
    u = [1,2,3]
    w = u
    w[1] = 0
    u = t

    Some people will tell you to use different words but the behaviour of
    the language doesn't change.
    Jussi Piitulainen, Dec 4, 2012
    #3
    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. pit3k
    Replies:
    2
    Views:
    1,006
    sadhu
    Feb 8, 2005
  2. Replies:
    5
    Views:
    409
  3. radio
    Replies:
    5
    Views:
    175
    radio
    Jul 22, 2004
  4. Andrew Falanga
    Replies:
    2
    Views:
    201
    Andrew Falanga
    Nov 22, 2008
  5. Thomas Bach

    Re: scope, function, mutable

    Thomas Bach, Dec 4, 2012, in forum: Python
    Replies:
    0
    Views:
    177
    Thomas Bach
    Dec 4, 2012
Loading...

Share This Page