Class initialization from a dictionary, how best?

Discussion in 'Python' started by brianobush@gmail.com, Jan 14, 2005.

  1. Guest

    #
    # My problem is that I want to create a
    # class, but the variables aren't known
    # all at once. So, I use a dictionary to
    # store the values in temporarily.
    # Then when I have a complete set, I want to
    # init a class from that dictionary.
    # However, I don't want to specify the
    # dictionary gets by hand
    # since it is error prone.
    # Thanks for any ideas, Brian


    # So I have a class defined that accepts a number of variables
    # and they must be all present at object creation time.
    class Test:
    def __init__(self, a, b, c):
    self.a = a
    self.b = b
    self.c = c
    def __str__(self):
    return '%s, %s, %d' % (self.a, self.b, self.c)

    # For example:
    t1 = Test('asd', 'sdf', 9)
    print t1

    # However, due to parsing XML, I am
    # creating the values incrementally
    # and I want to store them in a dictionary
    # and then map them easily to a class

    dictionary = {}

    # a mapping from source to destination
    mapping = {
    'a': str,
    'b': str,
    'c': int,
    }

    # a sample source of values
    test_source = {
    'a': 'test',
    'b': 'asdf',
    'c': 45
    }

    # now we go through and extract the values
    # from our source and build the dictionary

    for attr_name, function in mapping.items():
    dictionary[attr_name] = function(test_source.get(attr_name))

    print dictionary

    # Here is the problem I want to avoid:
    # Having to list the variable names
    # as strings in multiple places. It is enought to
    # have them in the 'mapping'
    # dictionary above

    t2 = Test(dictionary.get('a'), dictionary.get('b'),
    dictionary.get('c'))
    print t2
     
    , Jan 14, 2005
    #1
    1. Advertising

  2. Nick Coghlan Guest

    wrote:
    > t2 = Test(dictionary.get('a'), dictionary.get('b'),
    > dictionary.get('c'))
    > print t2


    Try this:

    t2 = Test(**dictionary)

    This performs keyword argument expansion on the dictionary, matching the
    dictionary entries with the named arguments to the Test.__init__ function.

    Cheers,
    Nick.

    --
    Nick Coghlan | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
     
    Nick Coghlan, Jan 14, 2005
    #2
    1. Advertising

  3. On 13 Jan 2005 20:36:19 -0800, "" <> wrote:

    >#
    ># My problem is that I want to create a
    ># class, but the variables aren't known
    ># all at once. So, I use a dictionary to
    ># store the values in temporarily.

    Why?
    ># Then when I have a complete set, I want to
    ># init a class from that dictionary.

    Why do it that way?

    ># However, I don't want to specify the
    ># dictionary gets by hand
    ># since it is error prone.
    ># Thanks for any ideas, Brian
    >
    >
    > So I have a class defined that accepts a number of variables
    ># and they must be all present at object creation time.

    Why? Why not a method to check if it's valid yet, and then
    add the attributes as they're available, without intermediaries.
    You can make Test "smart" so it won't accept any other names than a,b,c
    and will automatically convert to str, str, and int. Etc.

    What are you actually doing? Is this a toy example of a more complex class?

    >class Test:
    >def __init__(self, a, b, c):
    >self.a = a
    >self.b = b
    >self.c = c
    >def __str__(self):
    >return '%s, %s, %d' % (self.a, self.b, self.c)
    >
    ># For example:
    >t1 = Test('asd', 'sdf', 9)
    >print t1
    >
    ># However, due to parsing XML, I am
    ># creating the values incrementally
    ># and I want to store them in a dictionary
    ># and then map them easily to a class

    Why store them in a dictionary? Why not create an empty Test instance,
    and incrementally add the attributes directly as they're available?

    What are you going to do with t1 and other instances?

    >
    >dictionary = {}
    >
    ># a mapping from source to destination
    >mapping = {
    >'a': str,
    >'b': str,
    >'c': int,
    >}
    >
    ># a sample source of values
    >test_source = {
    >'a': 'test',
    >'b': 'asdf',
    >'c': 45
    >}
    >
    ># now we go through and extract the values
    ># from our source and build the dictionary

    Just the three items in the test_source dictionary?
    Is that just a 3-item holding place until you
    >
    >for attr_name, function in mapping.items():
    >dictionary[attr_name] = function(test_source.get(attr_name))
    >
    >print dictionary
    >
    ># Here is the problem I want to avoid:
    ># Having to list the variable names
    ># as strings in multiple places. It is enought to
    ># have them in the 'mapping'
    ># dictionary above
    >
    >t2 = Test(dictionary.get('a'), dictionary.get('b'),
    >dictionary.get('c'))
    >print t2
    >

    Why don't you just let Test do all the work, and update it incrementally
    until it is complete. You can use descriptors to manage state. You could
    do any number of things. The main problem is defining the _requirements_
    without premature implementation, never mind premature optimization ;-)

    You may have good reasons for wanting to do what you seem to want to do,
    but the picture is not clear to me ;-)

    Regards,
    Bengt Richter
     
    Bengt Richter, Jan 14, 2005
    #3
  4. Guest

    Yes, my examle here is a tiny part of a larger more complex issue. My
    application is an DOM XML parser that is reading attributes one at a
    time. My class that I am creating is used elsewhere and must have
    certain arguments for those uses to continue working. So, I seem to be
    left with creating an intermediate object. Before, I was simply
    creating an object:

    t = Test()
    for attr_name in mapping.keys():
    setattr(t, attr_name, value_from_source)

    This I feel was ellegant, efficient and clear. However, what I have now
    works but is not clear.
    BTW, t1 is just for example and was just being printed
    Thanks, Brian
     
    , Jan 14, 2005
    #4
  5. On 14 Jan 2005 07:32:06 -0800, "" <> wrote:

    >Yes, my examle here is a tiny part of a larger more complex issue. My
    >application is an DOM XML parser that is reading attributes one at a

    you mean like <tag attname="value" att2="v2">blah blah</tag> and you are
    grabbing things of interest out of a stream of info you are getting
    from call-backs? Or the equivalent?
    >time. My class that I am creating is used elsewhere and must have
    >certain arguments for those uses to continue working. So, I seem to be
    >left with creating an intermediate object. Before, I was simply

    Unless the "intermediate object" accumulates information for multiple
    Test() instances, why couldn't t= Test() be its own "intermediate object"?

    If you are accumulating info for multiple instances before creating them
    it is not clear from your description.

    >creating an object:
    >
    >t = Test()
    >for attr_name in mapping.keys():
    >setattr(t, attr_name, value_from_source)
    >
    >This I feel was ellegant, efficient and clear. However, what I have now
    >works but is not clear.
    >BTW, t1 is just for example and was just being printed


    What about giving Test some methods to do what you'd like? E.g., a micro-step
    in that direction from the above would let you write

    t = Test()
    ...
    t.load_info(infosource)

    Then the question becomes what infosource should be, or whether you really
    need it at all. IOW, if you are doing infosource.add_info(info_id, info_value)
    why couldn't you do t.add_info(info_id, info_value), unless you have to
    do t2.add_info(...) alternately with t.add_info(...), and if that's the case,
    what is the criterion for choosing t vs t2? Maybe that could be done by something
    that automatically manufactures t's as needed in a pool of partially complete t's.

    But your real requirements are not clear enough here, so you may get help crossing
    a stream, but no one will be able to say you are already on the side of the stream
    you want to be later, and there's an easy path without need of crossing twice ;-)

    Regards,
    Bengt Richter
     
    Bengt Richter, Jan 14, 2005
    #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. JKop
    Replies:
    10
    Views:
    960
  2. Matthias Kaeppler
    Replies:
    2
    Views:
    457
    Victor Bazarov
    Jul 18, 2005
  3. Replies:
    6
    Views:
    471
    Ron Natalie
    Dec 11, 2005
  4. toton
    Replies:
    5
    Views:
    943
    Victor Bazarov
    Sep 28, 2006
  5. Jess
    Replies:
    23
    Views:
    953
Loading...

Share This Page