Link to home
Start Free TrialLog in
Avatar of PMembrey
PMembrey

asked on

Object appears to be sharing a dictionary

Hi,

I've got an object that maintains a dictionary. It has a "get_or_create" method that accepts a string as a key. It then looks up the key in the dictionary and either returns a 'Store' object if it finds a match or creates one and returns that.

The idea is that I can request a Store object by passing a key and if it already exists I get that or it will simply create me a blank object.

The code for the StoreContainer looks like this:

class StoreContainer:
  stores{}

   def get_or_create_store(self,key):
        if key not in self.stores():
           self.stores[sc] = Store()
           self.stores[sc].id = key
       return(self.stores[sc])

Note: I don't have the exact code here so the indentation is approximate.

It seems to create all the stores fine but when I then add items to the stores, all the store items get it. I'm wondering if I'm just doing something obviously wrong - but I'm not sure what...

Avatar of PMembrey
PMembrey

ASKER

I've found that :

a =  main.get_or_create_store("test1")
b =  main.get_or_create_store("test2")

a is b
False

But :

a.stores is b.stores
True

Right, it seems like by default, any variables declared in the class are static. This was confusing as there are loads of posts on the web about how Python does not support static variables and yet it appears (to me at least) that it's doing precisely that.

By deleting the dictionary definition and using __init__  to create self.stores, it worked perfectly.

This URL helped me solve it:

http://paltman.com/2007/jul/08/python-classes-and-variable-gotchas-2/

For future reference, can any expert explain what's going on here?
ASKER CERTIFIED SOLUTION
Avatar of pepr
pepr

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi pepr,

After I moved it into the __init__ method, it worked fine. This is probably the first Python project I've worked on that required using multiple objects of the same type.

So to cut a long story short, if I define the dictionary as self.stores = {} in the __init__ method, everything will be okay? :-)
Although, if you could explain why doing:

qty_of_sales = 0
value_of_sales = None

in the class definition seems to work, that would be great :-)
I know it is confusing for those who worked only with classical compiled languages.  (I was also the one ;)

The key is to get acquainted with what Python variable really is.  At the beginning, study the following code that prints the following:

C:\tmp\___python\PMembrey\Q_25092961>a.py
__main__.MyClass
MyClass
['__module__', 'value_of_sales', '__doc__', 'qty_of_sales']
0
None
['objectVar']
['__doc__', '__module__', 'objectVar', 'qty_of_sales', 'value_of_sales']
0
3
1000
333
1000
class MyClass:
    '''This is the doc string of MyClass.'''
    qty_of_sales = 0           # class variable
    value_of_sales = None      # another class variable
    
    
a = MyClass()                  # create the instance of the class (i.e. the object)
a.objectVar = 3                # the object member variable (not in the class)

print a.__class__              # Reference to the class metaobject. When converted
                               # to string, it is displayed as the full identifier
                               # of the class.
print a.__class__.__name__     # bare name of the class
print a.__class__.__dict__.keys()  # the class internal dictionary of members
print a.__class__.qty_of_sales     # access explicitly the class variables
print a.__class__.value_of_sales

print a.__dict__.keys()            # the object internal dictionary of members

print dir(a)     # the built-in function dir() returs all accessible members,
                 # both class and object variable

print a.qty_of_sales    # access the class variable via the object
print a.objectVar       # this cannot be accessed via the class metaobject

b = MyClass()           # another instance of the same class

b.__class__.value_of_sales = 1000 # modify the class variable via the object
print a.value_of_sales  # the same value can be observed via the other object

b.value_of_sales = 333  # set (created first) the value of the instance variable
print b.value_of_sales  # now the instance variable is prefered

print a.value_of_sales  # the a still has access to the class variable

Open in new window

And yes. You should define all instance variables in the .__init__() method.  Better to say, you can define them any time in any method, but you must always write self.myvar.  Anyway, it is a good idea to define them in the __init__().