[Tutor] assignment to 1 item in dict assigns to all items in
dict?
Jeff Shannon
jeff@ccvcorp.com
Fri Apr 11 13:19:02 2003
Chris Somerlot wrote:
>>What are you trying to do exactly? The problem seems to stem from the
>>subtle difference between references and copies.
>>
>
>I see that you're right, I want to create a new instance of line_item
>each time and add it into the dictionary grossinc instead of making a
>reference, but I'm still confused about a good way to do that. Make a
>class?
>
You could do this with a class, and that would probably be my preferred
way, especially if there's any common tasks that need to be done on
line_items -- those can easily become methods of the class.
You can also continue using nested lists and dictionaries, just be sure
to create new ones for each line_item instead of just referring to the
same one. This can be done by using copy.deepcopy(), as Sean suggested,
or you could write a quick "factory function" that creates a new,
independent line_item each time it's called.
def new_line_item():
return [ {'Date': ()}, [], 0 ]
grossinc['salary'] = new_line_item()
grossinc['interest'] = new_line_item()
grossinc['dividends'] = new_line_item()
grossinc['other'] = new_line_item()
However, I do think that a class will allow you more flexibility later
on, not to mention ease of use.
class line_item:
def __init__(self, trans = None, assoc = None, goal = 0):
if not trans:
trans = {'Date': ()}
if not assoc:
assoc = []
self.transactions = trans
self.associations = assoc
self.goal = goal
grossinc['salary'] = line_item()
grossinc['interest'] = line_item()
grossinc['dividends'] = line_item()
grossinc['other'] = line_item(goal = 575)
grossinc['salary'].goal = 3333
Note that this makes it easier to refer to parts of each line item,
since you can use a named attribute instead of the cryptic [2], and it
also allows for more flexibility in creating items that are already
initalized.
By the way, you may wonder why I have default values of "None" for the
dict and list attributes, and then create the appropriate object later.
This is because default parameters are only evaluated once, so if I had
a dict or list as a default parameter, you'd end up with every line_item
having references to the *same* dict and list -- a close parallel to
your original problem. By passing in None as the default, and then
creating new objects as needed, I ensure that every line_item gets its
own transaction dict and associations list. (I don't bother with this
for the goal, because integers are not mutable, therefore it doesn't
really matter if all line_items share the same 0 or not.) See
http://www.python.org/doc/FAQ.html#6.25 for a bit more information about
this.
Jeff Shannon
Technician/Programmer
Credit International