0
class test(object): 
    def __init__(self): 
        self.a = 5 
        self.d = {'alfa': self.a}

I instantiate an object of the class, and assign a new value to it:

a_test = test()
a_test.a = 7

Why does a_test.d['alfa'] remain 5 and not change to 7?

TerryA
  • 58,805
  • 11
  • 114
  • 143
sfranky
  • 240
  • 2
  • 7
  • The problem is I have 40 of these attributes, and they are populated by parsing an html file. The tags come in randomly, so I thought I could use a dictionary instead of 40 ifs .. but I hate having to access attributes by saying a_test.d['alfa'] and not a_test.a – sfranky Feb 26 '13 at 09:48
  • Maybe you could show some more specific code which shows how you are constructing your objects, and we could suggest some solutions. – Daniel Roseman Feb 26 '13 at 09:54
  • (can I do this in the same question?) – sfranky Feb 26 '13 at 09:56
  • Yup, just click on [edit] below your post and add it in! – Jon Clements Feb 26 '13 at 11:16
  • I know how to do it, the problem is, it will transform the initial question entirely, and I m not sure this is OK. Plus, I don't really know anything about OOP, so maybe I should do some basic reading before I go on and post something trivial. – sfranky Feb 26 '13 at 12:11

5 Answers5

2

Because self.a contains the value 5 when you assign it in the dictionary. Integers are immutable so no reference is made. Please read about Python's data model.

Fabian
  • 4,160
  • 20
  • 32
1

You create the dictionary when you call the constructor. Therefore the values in the dictionary are set during construction - they aren't passed by reference, but rather by value.

The values in the dictionary point to value of the object that is passed in, but not the object itself. So simply having self.a as a value doesn't automatically update the dictionary, unless self.a is mutable (eg. a list).

Volatility
  • 31,232
  • 10
  • 80
  • 89
1

Let me propose my DictObjclass, which I've been using for issues like this:

class DictObj(dict):
    """
    a dictionary like class that allows attribute-like access to its keys

    d = DictObj(a=2, b=7)
    d['a']  --> 2
    d.a     --> 2

    """
    def __getattr__(self, name):
        return self.__getitem__(name)


    def __setattr__(self, name, value):
        if name in self:
            self.__setitem__(name, value)
        else:
            super(DictObj, self).__setattr__(name, value)


    def __add__(self, other):
        res = DictObj(self)
        res.update(other)
        return res

Items are stored in the dictionary, but can alternatively be accessed as attributes of the object.

You can extend this easily with more magic methods to suit your needs.

Ber
  • 40,356
  • 16
  • 72
  • 88
0

You should add a setter for manage your class instance:

def set_a(self, new_val):
   self.a = new_val
   self.d = {'alfa': self.a}
Zulu
  • 8,765
  • 9
  • 49
  • 56
  • 1
    But not this way, please. Setter methods are not encouraged in Python. Instead, use a property with the getters and setters bound to it. – glglgl Feb 26 '13 at 09:43
0
>>> a = 5
>>> b = {"key":a}
>>> b
{'key': 5}
>>> a = 7
>>> b
{'key': 5}
>>> 

you can see here that at the assigning instance value of "a" passed to dictionary "b" and it is 5.

so b['key'] has value 5 not reference of a. So no matter you are changing value at reference of a.

chirag ghiyad
  • 690
  • 1
  • 6
  • 14