0

I don't know if I'm missing something extremely obvious, but i found this behaviour to be surprising.

EDIT: Ok so here is an example where i do not use any default arguments - unlike linked duplicate - and it still behaves that way. Can someone please explain why?

class Manager(object):
    @classmethod
    def calculatesomething(cls, array, attr):
        array.append(attr)
        return 1

class MyClass(object):
    def __init__(self, array):
        self.array = array

    def __getattr__(self, attr):
        variable = Manager.calculatesomething(self.array, attr)
        return variable


a = MyClass(['one', 'two', 'three'])
print a.array
print a.four
print a.array

Output:

['one', 'two', 'three']
1
['one', 'two', 'three', 'four']

What i expected:

['one', 'two', 'three']
1
['one', 'two', 'three']

Just like when we have a simple function:

def f(a):
    a += 1
    return a
a = 1

print a
print f(a)
print a

I expect:

1
2
1

and that's exactly what i get.

Kesto
  • 625
  • 1
  • 8
  • 17
  • What exactly is surprising to you about this behaviour? What do you *expect* instead? – deceze Jan 20 '17 at 14:53
  • @deceze I find it surprising that method 'calculatesomething' can actually change array instance variable of MyClass(). I will add further information what i expected. – Kesto Jan 20 '17 at 14:57
  • 1
    You are passing (a reference to) a `list` object and are mutating that object. There's no copy being created of `self.array` when you pass it into another function, you're passing *the one and only instance* of the object. – deceze Jan 20 '17 at 14:59
  • 1
    This has been treated in quite a few questions here, really. – bruno desthuilliers Jan 20 '17 at 14:59
  • 1
    `+=` reassigns a variable, it doesn't mutate the instance like `.append()` does. – deceze Jan 20 '17 at 15:00
  • @deceze except when the class redefines `__radd__` to mutate itself, cf `list.__radd__` which calls `self.extend` and returns `self` ;) – bruno desthuilliers Jan 20 '17 at 15:02
  • @bruno Let's keep it simple, shall we? ;) – deceze Jan 20 '17 at 15:03
  • @Kesto deceze is still right in that your "simple function" example rebinds a local name. Rewrite it using a list and mutating that list (well, using just any mutable object and mutating it) and you'll find out. – bruno desthuilliers Jan 20 '17 at 15:04
  • @deceze well if the op was to try it's "simple function" with a list and using `+=another_list` on it he would be ever more perplexed xD – bruno desthuilliers Jan 20 '17 at 15:05
  • So basically i have to create a new list, extend it by 'array' and then append 'attr' to it? It works perfectly fine this way, but i'd like to know if this is the correct way to work with this problem. This is kinda embarassing. – Kesto Jan 20 '17 at 15:07

0 Answers0