Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > always the same object (2)

Reply
Thread Tools

always the same object (2)

 
 
Uwe Mayer
Guest
Posts: n/a
 
      01-21-2004
Hi,

sorry for the lack of source code.
Here again:

I use struct.unpack() to unpack data from a binary file and pass the
returned tuple as parameter to __init__ of a class that's supposed to
handle the data:

class DataWrapper():
data = { }
def __init__(self, arg): #arg will contain a tuple
data['var1'], data['var2'] = arg


result = [ ]
while not <end-of-file f>:
data = struc.unpack("4s4s", f.read()
record = DataWrapper( data ) # pass tuple from unpack
result.append( record )

Then "result" contains a list with different objects, but the strings
in data['var1'] and data['var2'] are all the same.

Any ideas how to avoid this?

Thanks again
Ciao
Uwe
 
Reply With Quote
 
 
 
 
Uwe Mayer
Guest
Posts: n/a
 
      01-21-2004
Uwe Mayer wrote:

Thanks for all the responses. As John Roth <(E-Mail Removed)> wrote
in <(E-Mail Removed)>:

> class DataWrapper():
> data = { }
> def __init__(self, arg): #arg will contain a tuple
> data['var1'], data['var2'] = arg


the "data" variable is a class variable and shared by all DataWrapper,
therfore:

> result = [ ]
> while not <end-of-file f>:
> data = struc.unpack("4s4s", f.read()
> record = DataWrapper( data ) # pass tuple from unpack
> result.append( record )


all "record"s in "result" share the same instance and thus all the data gets
overwritten.

Moving "data" into __init__() in DataWrapper does the trick.

Thanks again
Ciao
Uwe
 
Reply With Quote
 
 
 
 
David Bolen
Guest
Posts: n/a
 
      01-21-2004
Uwe Mayer <(E-Mail Removed)> writes:

(...)
> I use struct.unpack() to unpack data from a binary file and pass the
> returned tuple as parameter to __init__ of a class that's supposed to
> handle the data:
>
> class DataWrapper():
> data = { }
> def __init__(self, arg): #arg will contain a tuple
> data['var1'], data['var2'] = arg


Is this actual code? You should get a SyntaxError on your use of ()
in the class line, and a NameError on your use of data[] since there
is no local data name within the __init__ function. I'm assuming your
real code actually does self.data, and skips the () on the class
statement, but in the future, it's really best if you can post actual
operating code when discussing a problem.

> result = [ ]
> while not <end-of-file f>:
> data = struc.unpack("4s4s", f.read()
> record = DataWrapper( data ) # pass tuple from unpack
> result.append( record )
>
> Then "result" contains a list with different objects, but the strings
> in data['var1'] and data['var2'] are all the same.
>
> Any ideas how to avoid this?


Yes, don't make data a class-level object. By doing this you have a
single instance of the dictionary that data is pointing to, which is
shared among all of your DataWrapper instances. Since that class
object is mutable, all of your changes in each instances __init__
affect that single object. Instead, move the creation of the instance
name (and object) to the __init__ in your instance.

This can be a subtle point sometimes, because you won't run into this
problem with class level immutable objects (such as ints), because any
assignment to the same name in an instance becomes a rebinding
operation, thus making the name an instance variable at that point in
time. This can be very convenient for implementing class level
defaults that take up no space in each instance, but doesn't work the
same as mutable types.

Note that if you really mean to do it, using a mutable type at class
level can be a very useful construct, since it permits sharing of
information among all instances of a class. But you have to be
expecting it

For example, the immutable case:

>>> class Foo:

... var = 10
... def set_var(self, value):
... print 'Var ID:', id(self.var)
... self.var = value
... print 'Var ID:', id(self.var)
...
>>> x = Foo()
>>> print id(Foo.var), id(x.var)

7649236 7649236
>>> x.set_var(5)

Var ID: 7649236
Var ID: 7649224
>>> print id(Foo.var), id(x.var)

7649236 7649224
>>> print Foo.var, x.var

10 5

Foo.var always references the same object, but once an assignment has
been made within the instance, it no longer points to the same object
as initialized at class level. Thus, each instance references
independent objects with their own values.

Contrast this with the mutable case:

>>> class Foo:

... var = []
... def set_var(self, value):
... print 'Var ID:', id(self.var)
... self.var.append(value)
... print 'Var ID:', id(self.var)
...
>>> x = Foo()
>>> y = Foo()
>>> print id(Foo.var), id(x.var), id(y.var)

8042256 8042256 8042256
>>> print Foo.var, x.var, y.var

[] [] []
>>> x.set_var(10)

Var ID: 8042256
Var ID: 8042256
>>> y.set_var(5)

Var ID: 8042256
Var ID: 8042256
>>> print id(Foo.var), id(x.var), id(y.var)

8042256 8042256 8042256
>>> print Foo.var, x.var, y.var

[10, 5] [10, 5] [10, 5]

I made the class object a list and appended values to it just to
highlight how calls to multiple instances were affecting the same
object, but the principle is the same with a dictionary or any other
mutable object. Since the changes in set_var are made by mutating the
existing object (versus rebinding the same name to a new object), all
the instances share the single Foo.var list.

So you could use this construct if you really wanted an object that
was seen by all instances and updated by any instance. But if you
just wanted an empty list (or dictionary) independently in each
instance, you'd want to do something like:

>>> class Foo:

... def __init__(self):
... self.var = []
... def set_var(self, value):
... print 'Var ID:', id(self.var)
... self.var.append(value)
... print 'Var ID:', id(self.var)
...
>>> x = Foo()
>>> y = Foo()
>>> print id(Foo.var)

Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: class Foo has no attribute 'var'
>>> print id(x.var), id(y.var)

7756800 8053200
>>> x.set_var(10)

Var ID: 7756800
Var ID: 7756800
>>> y.set_var(5)

Var ID: 8053200
Var ID: 8053200
>>> print id(x.var), id(y.var)

7756800 8053200
>>> print x.var, y.var

[10] [5]

-- David
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
same object share same static variable??? Mug C++ 4 09-03-2009 12:51 PM
Object creation - Do we really need to create a parent for a derieved object - can't the base object just point to an already created base object jon wayne C++ 9 09-22-2005 02:06 AM
Trying to create a CSS box that is always is always the width of an image placed inside it (and no wider) Deryck HTML 4 06-22-2004 08:25 PM
always the same object Uwe Mayer Python 3 01-21-2004 12:04 AM
why did this hashmap always returned the same object? ravi mannan Java 2 11-23-2003 10:10 PM



Advertisments