Help with dynamic attributes.

Discussion in 'Python' started by Mr.Rech, Jan 9, 2006.

  1. Mr.Rech

    Mr.Rech Guest

    Hi all,
    I was writing a simple class when I get a strange error message that I
    can't
    understand. Hopefully someone could help me here.

    My class's init method takes a list of lists as input argument and I'd
    like to create
    several attributes each one referencing one item of the passed list.
    Easy-of-use arguments
    has led me to call these attributes as x0, x1, x2 and so on. In order
    to get as many
    attributes as the number of items of the passed list dynamically
    defined I wrote the
    following code:

    class foo(object):
    def __init__(self, list_of_lists):
    self.lol = list(list_of_lists)

    for i in range(len(list_of_lists)):
    exec 'self.x%d = self.lol[%d]' % (i, i)

    self.shape = tuple(len(item) for item in self.lol)

    As soon as I try to import the module in which this class is defined I
    get the following
    error message:

    SyntaxError: unqualified exec is not allowed in function '__init__' it
    contains a nested
    function with free variables (module_name.py, line 49)

    After a little bit of trials and errors I found that if I comment out
    the line

    self.shape = tuple(len(item) for item in self.lol)

    or I rewrote the for cycle as follows:

    for i in range(len(list_of_lists)):
    exec 'self.x%d = self.lol[%d]' % (i, i) in locals()

    the error disappears and the code works as expected. What it is even
    more strange to me is
    that if I replace the generator expression statement (that defines
    self.shape) with an
    explicit for-loop the error message doesn't come in and the code works
    flawlessly.

    I really can't understand why it happens and I'm wondering what it's
    going on here behind
    the scene. Any explanation? Any better way to get the same attributes I
    got with the exec
    statement?

    Thanks in advance,
    Andrea
     
    Mr.Rech, Jan 9, 2006
    #1
    1. Advertising

  2. "Mr.Rech" wrote:

    > class foo(object):
    > def __init__(self, list_of_lists):
    > self.lol = list(list_of_lists)
    >
    > for i in range(len(list_of_lists)):
    > exec 'self.x%d = self.lol[%d]' % (i, i)
    >
    > self.shape = tuple(len(item) for item in self.lol)


    generator expressions are anonymous functions, and the "self" in that line
    is a free variable (that is, it belongs to an outer scope). Python uses static
    analysis to identify free variables, and that doesn't mix well with exec.

    > Any better way to get the same attributes I got with the exec statement?


    use setattr(self, name, value)

    </F>
     
    Fredrik Lundh, Jan 9, 2006
    #2
    1. Advertising

  3. Mr.Rech

    Mr.Rech Guest

    I would have sworn that it had been a better way to get it.

    Thanks a lot,
    Andrea
     
    Mr.Rech, Jan 9, 2006
    #3
  4. Mr.Rech a écrit :
    (snip)
    >
    > My class's init method takes a list of lists as input argument and I'd
    > like to create
    > several attributes each one referencing one item of the passed list.
    >
    > Easy-of-use arguments
    > has led me to call these attributes as x0, x1, x2 and so on.


    This is a very wrong design IM(ns)HO. A 'has-many' semantic is better
    expressed by a multivalued attribute (ie : list, tuple or dict) than by
    an undefined number of monovalued attributes. Also, the way you're
    trying to implement it, you will loose sync between individual
    monovalued attributes and the list of lists.

    My 2 cents
     
    Bruno Desthuilliers, Jan 9, 2006
    #4
  5. Mr.Rech

    Mike Meyer Guest

    "Mr.Rech" <> writes:
    > Hi all,
    > I was writing a simple class when I get a strange error message that I
    > can't
    > understand. Hopefully someone could help me here.
    >
    > My class's init method takes a list of lists as input argument and I'd
    > like to create
    > several attributes each one referencing one item of the passed list.


    Why? You save all of two characters per reference over doing a simple

    self.x = list(self.lol)

    <mike
    --
    Mike Meyer <> http://www.mired.org/home/mwm/
    Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
     
    Mike Meyer, Jan 10, 2006
    #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. Max
    Replies:
    1
    Views:
    482
    Joe Kesselman
    Sep 22, 2006
  2. P4trykx
    Replies:
    2
    Views:
    1,822
    bruce barker
    Jan 31, 2007
  3. james_027

    class attributes & data attributes

    james_027, Jun 20, 2007, in forum: Python
    Replies:
    2
    Views:
    375
    Bruno Desthuilliers
    Jun 20, 2007
  4. Kyle Schmitt
    Replies:
    3
    Views:
    192
    Kyle Schmitt
    Jul 24, 2007
  5. Jayden
    Replies:
    16
    Views:
    526
    Steven D'Aprano
    Sep 29, 2012
Loading...

Share This Page