0

I have a certain custom class that looks like a dictionary, and I want a method to be able to modify the values of the dictionary, but somehow I seem to be able to do so only by key-by-key modification (rather than self=... assignment).

Obviously I want something more complex that the following MWE, but it demonstrates my issue (I would expect both class methods below to be equivalent):

class MyClass(dict):
    def addone_notworking(self):
        self = {key: (val+1) for key, val in self.items()}
        # print({key: (val+1) for key, val in self.items()}) would return what I expect

    def addone_working(self):
        for k in self:
            self[k] += 1  # self[k] = self[k] + 1 would work as well

a = MyClass({'a':1, 'b':2})
print(a, '<-- original')
a.addone_notworking()
print(a, "<-- should have added 1, but it hasn't")
a.addone_working()
print(a, '<-- works')

Results:

{'a': 1, 'b': 2} <-- original
{'a': 1, 'b': 2} <-- should have added 1, but hasn't
{'a': 2, 'b': 3} <-- works

What am I missing? I have found Python class methods changing self but I doubt it really applies ( bar = foo statements would work even if bar was a non-mutable type).

(Python 3.5, if it matters)

JM114516
  • 125
  • 2
  • `self` is just a local variable like any other. Assigning to variables doesn't mutate objects. See https://nedbatchelder.com/text/names.html – user2357112 Mar 27 '18 at 17:01
  • Consider `self.update()` for bulk changing of values in a dict subclass. – jasonharper Mar 27 '18 at 17:03
  • The fix b.t.w is `self.update(**{key: (val+1) for key, val in self.items()})`. – mr_mo Mar 27 '18 at 17:03
  • Here's a related question: https://stackoverflow.com/questions/1216356/is-it-safe-to-replace-a-self-object-by-another-object-of-the-same-type-in-a-meth – Arya Mar 27 '18 at 17:04
  • @user2357112 I was (vaguely) aware of the contents of your link, but I still fail to see why the two methods should work differently. If self is purely a local variable inside the method, then `addone_working` should not work (but it does) – JM114516 Mar 27 '18 at 17:14
  • 1
    `addone_working` isn't assigning to the local variable. It's assigning to a dict entry. – user2357112 Mar 27 '18 at 17:19
  • @mr_mo You don't even need to unpack it, `dict.update` can take either a dictionary or keyword arguments (or both). – Graipher Mar 27 '18 at 18:02

0 Answers0