python newbie - question about lexical scoping

Discussion in 'Python' started by Matt Barnicle, Dec 1, 2007.

  1. hi everyone.. i've been chugging along learning python for a few months
    now and getting answers to all needed questions on my own, but this one
    i can't figure out nor can i find information on the internet about it,
    possibly because i don't understand the right words to type into google..

    i have a very common scenario and need to know the python way to do it.
    take this example loop:

    comments = []
    for row in rows:
    comment = models.comment()
    comment.author = row[1]
    comment.text = row[0]
    comments.append(comment)

    the problem is that when i go to retrieve the comments later, they are
    all the same object! i assume this is due to there being no lexical
    scoping? so what is the solution to this?

    thank u all!

    - m@
     
    Matt Barnicle, Dec 1, 2007
    #1
    1. Advertising

  2. Matt Barnicle

    John Machin Guest

    On Dec 1, 4:47 pm, Matt Barnicle <> wrote:
    > hi everyone.. i've been chugging along learning python for a few months
    > now and getting answers to all needed questions on my own, but this one
    > i can't figure out nor can i find information on the internet about it,
    > possibly because i don't understand the right words to type into google..
    >
    > i have a very common scenario and need to know the python way to do it.
    > take this example loop:
    >
    > comments = []
    > for row in rows:
    > comment = models.comment()


    Insert here:
    print type(comment), id(comment), repr(row[:2])

    > comment.author = row[1]
    > comment.text = row[0]
    > comments.append(comment)
    >
    > the problem is that when i go to retrieve the comments later, they are
    > all the same object! i assume this is due to there being no lexical
    > scoping? so what is the solution to this?


    And the attributes of the "same object" match the first two elements
    of which input row:
    (a) rows[0]
    (b) rows[-1]
    (c) some other row
    (d) you can't tell because all input rows have the same value in each
    of row[0] and row[1]
    (e) none of the above?

    It's nothing to do with lexical scoping, at least in the code that
    you've shown us, which has no apparent problems. You need to show us
    the code for the models.comment function/method/class. Possibly it is
    returning the same object each time it is invoked (answer (b) above);
    the above print statement will help investigate that possibility, plus
    the possibility that the objects are not the same objects, but are
    different objects with the same attributes (answer (d) above). Also
    show us the code for retrieving the comments later; possibly you are
    retrieving the same element of the comments list each time. Use this:
    print [id(x) for x in comments]
    to verify your assertion that they are all the same object.

    Cheers,
    John
     
    John Machin, Dec 1, 2007
    #2
    1. Advertising

  3. > On Dec 1, 4:47 pm, Matt Barnicle <> wrote:
    >> hi everyone.. i've been chugging along learning python for a few months
    >> now and getting answers to all needed questions on my own, but this one
    >> i can't figure out nor can i find information on the internet about it,
    >> possibly because i don't understand the right words to type into
    >> google..
    >>
    >> i have a very common scenario and need to know the python way to do it.
    >> take this example loop:
    >>
    >> comments = []
    >> for row in rows:
    >> comment = models.comment()

    >
    > Insert here:
    > print type(comment), id(comment), repr(row[:2])
    >
    >> comment.author = row[1]
    >> comment.text = row[0]
    >> comments.append(comment)
    >>
    >> the problem is that when i go to retrieve the comments later, they are
    >> all the same object! i assume this is due to there being no lexical
    >> scoping? so what is the solution to this?

    >
    > And the attributes of the "same object" match the first two elements
    > of which input row:
    > (a) rows[0]
    > (b) rows[-1]
    > (c) some other row
    > (d) you can't tell because all input rows have the same value in each
    > of row[0] and row[1]
    > (e) none of the above?
    >
    > It's nothing to do with lexical scoping, at least in the code that
    > you've shown us, which has no apparent problems. You need to show us
    > the code for the models.comment function/method/class. Possibly it is
    > returning the same object each time it is invoked (answer (b) above);
    > the above print statement will help investigate that possibility, plus
    > the possibility that the objects are not the same objects, but are
    > different objects with the same attributes (answer (d) above). Also
    > show us the code for retrieving the comments later; possibly you are
    > retrieving the same element of the comments list each time. Use this:
    > print [id(x) for x in comments]
    > to verify your assertion that they are all the same object.
    >
    > Cheers,
    > John


    aye yaye aye... thanks for the pointers in the right direction.. i
    fiddled around with the code for a while and now i've reduced it to the
    *real* issue... i have a class dict variable that apparently holds its
    value across instantiations of new objects.. the problem can be
    illustrated in the following much simpler code:

    >>> class foo():

    .... bar = { 'baz': 'bing' }
    ....
    >>> a = foo()
    >>> a.bar

    {'baz': 'bing'}
    >>> a.bar['baz'] = 'bong'
    >>> a.bar

    {'baz': 'bong'}
    >>> b = foo()
    >>> b.bar

    {'baz': 'bong'}
     
    Matt Barnicle, Dec 2, 2007
    #3
  4. > On Dec 1, 4:47 pm, Matt Barnicle <> wrote:
    >> hi everyone.. i've been chugging along learning python for a few months
    >> now and getting answers to all needed questions on my own, but this one
    >> i can't figure out nor can i find information on the internet about it,
    >> possibly because i don't understand the right words to type into
    >> google..
    >>
    >> i have a very common scenario and need to know the python way to do it.
    >> take this example loop:
    >>
    >> comments = []
    >> for row in rows:
    >> comment = models.comment()

    >
    > Insert here:
    > print type(comment), id(comment), repr(row[:2])
    >
    >> comment.author = row[1]
    >> comment.text = row[0]
    >> comments.append(comment)
    >>
    >> the problem is that when i go to retrieve the comments later, they are
    >> all the same object! i assume this is due to there being no lexical
    >> scoping? so what is the solution to this?

    >
    > And the attributes of the "same object" match the first two elements
    > of which input row:
    > (a) rows[0]
    > (b) rows[-1]
    > (c) some other row
    > (d) you can't tell because all input rows have the same value in each
    > of row[0] and row[1]
    > (e) none of the above?
    >
    > It's nothing to do with lexical scoping, at least in the code that
    > you've shown us, which has no apparent problems. You need to show us
    > the code for the models.comment function/method/class. Possibly it is
    > returning the same object each time it is invoked (answer (b) above);
    > the above print statement will help investigate that possibility, plus
    > the possibility that the objects are not the same objects, but are
    > different objects with the same attributes (answer (d) above). Also
    > show us the code for retrieving the comments later; possibly you are
    > retrieving the same element of the comments list each time. Use this:
    > print [id(x) for x in comments]
    > to verify your assertion that they are all the same object.
    >
    > Cheers,
    > John


    aye yaye aye... thanks for the pointers in the right direction.. i
    fiddled around with the code for a while and now i've reduced it to the
    *real* issue... i have a class dict variable that apparently holds its
    value across instantiations of new objects.. the problem can be
    illustrated in the following much simpler code:

    >>> class foo():

    .... bar = { 'baz': 'bing' }
    ....
    >>> a = foo()
    >>> a.bar

    {'baz': 'bing'}
    >>> a.bar['baz'] = 'bong'
    >>> a.bar

    {'baz': 'bong'}
    >>> b = foo()
    >>> b.bar

    {'baz': 'bong'}
     
    Matt Barnicle, Dec 2, 2007
    #4
  5. Matt Barnicle

    Tim Roberts Guest

    Matt Barnicle <> wrote:

    >hi everyone.. i've been chugging along learning python for a few months
    >now and getting answers to all needed questions on my own, but this one
    >i can't figure out nor can i find information on the internet about it,
    >possibly because i don't understand the right words to type into google..
    >
    >i have a very common scenario and need to know the python way to do it.
    >take this example loop:
    >
    >comments = []
    >for row in rows:
    > comment = models.comment()
    > comment.author = row[1]
    > comment.text = row[0]
    > comments.append(comment)
    >
    >the problem is that when i go to retrieve the comments later, they are
    >all the same object! i assume this is due to there being no lexical
    >scoping? so what is the solution to this?


    Is that REALLY what the code looks like? Or does it actually look like
    this:

    comments = []
    comment = models.comment()
    for row in rows:
    comment.author = row[1]
    comment.text = row[0]
    comments.append(comment)

    That construct would produce exactly the result you describe. You would
    also get the result you describe if models.comment() were a normal function
    that returns a single object, instead of a class name, as I have assumed.
    --
    Tim Roberts,
    Providenza & Boekelheide, Inc.
     
    Tim Roberts, Dec 2, 2007
    #5
  6. >> On Dec 1, 4:47 pm, Matt Barnicle <> wrote:
    > aye yaye aye... thanks for the pointers in the right direction.. i
    > fiddled around with the code for a while and now i've reduced it to the
    > *real* issue... i have a class dict variable that apparently holds its
    > value across instantiations of new objects.. the problem can be
    > illustrated in the following much simpler code:
    >
    >>>> class foo():

    > ... bar = { 'baz': 'bing' }
    > ...
    >>>> a = foo()
    >>>> a.bar

    > {'baz': 'bing'}
    >>>> a.bar['baz'] = 'bong'
    >>>> a.bar

    > {'baz': 'bong'}
    >>>> b = foo()
    >>>> b.bar

    > {'baz': 'bong'}


    ok, i see... python has a concept i'm not accustomed to which i found
    described here:

    http://zephyrfalcon.org/labs/python_pitfalls.html
    4. Class attributes vs instance attributes

    so i'm sure what is going on is obvious to experienced python
    programmers... i'm not really sure how to get around this though. i'll
    need to spend some time on reworking our models code i guess... i
    inherited this from someone, and what he was trying to do was to set
    default values for objects representing tables (in kind of a simple ORM
    layer) and storing the values in a dict, and when the object is
    instantiated, the table is queried and the default dict values are
    overwritten. so obviously this method is not going to work as such..

    sorry for the misdirection, i didn't quite understand at first..

    - m@
     
    Matt Barnicle, Dec 2, 2007
    #6
  7. >> On Dec 1, 4:47 pm, Matt Barnicle <> wrote:
    > aye yaye aye... thanks for the pointers in the right direction.. i
    > fiddled around with the code for a while and now i've reduced it to the
    > *real* issue... i have a class dict variable that apparently holds its
    > value across instantiations of new objects.. the problem can be
    > illustrated in the following much simpler code:
    >
    >>>> class foo():

    > ... bar = { 'baz': 'bing' }
    > ...
    >>>> a = foo()
    >>>> a.bar

    > {'baz': 'bing'}
    >>>> a.bar['baz'] = 'bong'
    >>>> a.bar

    > {'baz': 'bong'}
    >>>> b = foo()
    >>>> b.bar

    > {'baz': 'bong'}


    ok, i see... python has a concept i'm not accustomed to which i found
    described here:

    http://zephyrfalcon.org/labs/python_pitfalls.html
    4. Class attributes vs instance attributes

    so i'm sure what is going on is obvious to experienced python
    programmers... i'm not really sure how to get around this though. i'll
    need to spend some time on reworking our models code i guess... i
    inherited this from someone, and what he was trying to do was to set
    default values for objects representing tables (in kind of a simple ORM
    layer) and storing the values in a dict, and when the object is
    instantiated, the table is queried and the default dict values are
    overwritten. so obviously this method is not going to work as such..

    sorry for the misdirection, i didn't quite understand at first..

    - m@
     
    Matt Barnicle, Dec 2, 2007
    #7
  8. "Matt Barnicle" <> writes:

    >> i have a class dict variable that apparently holds its value across
    >> instantiations of new objects..

    [...]
    > ok, i see... python has a concept i'm not accustomed to


    I don't doubt that Python managed to confuse you here, but in this
    case there is nothing really unusual or novel in Python's treatment of
    class variables. Equivalent Java code would behave exactly the same:

    class Foo {
    static Map bar = new HashMap();
    static {
    bar.put("baz", "bing");
    }
    }

    Foo a = new Foo();
    a.bar.put("baz", "bong");

    Foo b = new Foo();
    System.out.println(b.bar.get("baz"));
    -> "bong"

    > so i'm sure what is going on is obvious to experienced python
    > programmers... i'm not really sure how to get around this though.


    Simply do what you'd do in any other OO language: assign a fresh value
    to each instance in its constructor:

    class Foo(object):
    def __init__(self):
    self.bar = {'baz': 'bing'}

    Now each instance of Foo has a separate "bar" attribute dict which can
    be mutated without affecting other instances.
     
    Hrvoje Niksic, Dec 2, 2007
    #8
  9. Matt Barnicle a écrit :
    >>>On Dec 1, 4:47 pm, Matt Barnicle <> wrote:

    >>
    >>aye yaye aye... thanks for the pointers in the right direction.. i
    >>fiddled around with the code for a while and now i've reduced it to the
    >>*real* issue... i have a class dict variable that apparently holds its
    >>value across instantiations of new objects..


    If it's a class attribute, it's indeed shared between all instances...

    >> the problem can be
    >>illustrated in the following much simpler code:
    >>
    >>>>>class foo():

    >>
    >>... bar = { 'baz': 'bing' }

    (snip)
    > ok, i see... python has a concept i'm not accustomed to which i found
    > described here:
    >
    > http://zephyrfalcon.org/labs/python_pitfalls.html
    > 4. Class attributes vs instance attributes
    >
    > so i'm sure what is going on is obvious to experienced python
    > programmers... i'm not really sure how to get around this though.


    It's not a problem:

    class Foo(object):
    def __init__(self):
    self.bar = {'baz':'bing'}



    >i'll
    > need to spend some time on reworking our models code i guess... i
    > inherited this from someone, and what he was trying to do was to set
    > default values for objects representing tables (in kind of a simple ORM
    > layer) and storing the values in a dict, and when the object is
    > instantiated, the table is queried and the default dict values are
    > overwritten.


    class Foo(object):
    bar = {'baz':'bing'}
    def __init__(self):
    self.bar = self.bar
     
    Bruno Desthuilliers, Dec 2, 2007
    #9
  10. Matt Barnicle

    hdante Guest

    On Dec 1, 11:31 pm, "Matt Barnicle" <> wrote:
    > >> On Dec 1, 4:47 pm, Matt Barnicle <> wrote:

    > > aye yaye aye... thanks for the pointers in the right direction.. i
    > > fiddled around with the code for a while and now i've reduced it to the
    > > *real* issue... i have a class dict variable that apparently holds its
    > > value across instantiations of new objects.. the problem can be
    > > illustrated in the following much simpler code:

    >
    > >>>> class foo():

    > > ... bar = { 'baz': 'bing' }
    > > ...
    > >>>> a = foo()
    > >>>> a.bar

    > > {'baz': 'bing'}
    > >>>> a.bar['baz'] = 'bong'
    > >>>> a.bar

    > > {'baz': 'bong'}
    > >>>> b = foo()
    > >>>> b.bar

    > > {'baz': 'bong'}

    >
    > ok, i see... python has a concept i'm not accustomed to which i found
    > described here:
    >
    > http://zephyrfalcon.org/labs/python_pitfalls.html
    > 4. Class attributes vs instance attributes
    >
    > so i'm sure what is going on is obvious to experienced python
    > programmers... i'm not really sure how to get around this though. i'll
    > need to spend some time on reworking our models code i guess... i
    > inherited this from someone, and what he was trying to do was to set
    > default values for objects representing tables (in kind of a simple ORM
    > layer) and storing the values in a dict, and when the object is
    > instantiated, the table is queried and the default dict values are
    > overwritten. so obviously this method is not going to work as such..
    >
    > sorry for the misdirection, i didn't quite understand at first..
    >
    > - m@



    A trivial solution:

    class foo:
    default_bar = { 'baz' : 'bong' }
    def __init__(self):
    self.bar = self.default_bar.copy()
    self.bar['woo'] = 'wee'

    Note: it's not necessary to reimplement an ORM. Try using Django (if
    you need a complete solution) or Elixir (just the ORM).
     
    hdante, Dec 2, 2007
    #10
  11. Bruno Desthuilliers a écrit :
    (snip)


    > class Foo(object):
    > bar = {'baz':'bing'}
    > def __init__(self):
    > self.bar = self.bar


    Hem... Should re-read before posting :(

    It's of course:

    def __init__(self):
    self.bar = self.bar.copy()
     
    Bruno Desthuilliers, Dec 2, 2007
    #11
    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. Khookie

    C closures & lexical scoping

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

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

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

    Lexical scoping question.

    Louis., Feb 10, 2005, in forum: Perl Misc
    Replies:
    8
    Views:
    200
    Michael Powe
    Feb 11, 2005
  5. PerlFAQ Server
    Replies:
    0
    Views:
    366
    PerlFAQ Server
    Jan 6, 2011
Loading...

Share This Page