0

Do all instances of a given class share the same method object? I could not verify this directly using id. However I think the answer is yes, because the following works:

class A(object):
    def f(self, x, d=[]):
        d.append(x)
        print d
a = A()
b = A()
A.f(a, 3)
a.f(4)
b.f(5)

Out:

[3]
[3, 4]
[3, 4, 5]

Can anyone confirm or infirm this?

usual me
  • 8,338
  • 10
  • 52
  • 95
  • It's because [everything is a reference](http://stackoverflow.com/a/2322079/3336968) in python. – fredtantini Oct 06 '14 at 15:02
  • 1
    I don't _think_ this is a least astonishment issue. That would be if we called `a.f(4)`, then `a.f(5)`, and were surprised that the returned list was adding. This is asking whether the actual function `f` inside two created objects `a` and `b` of a type `A` are the _same_ function, or copies of an original function; it appears he already knows about the list duplication and is using that to test his theory. – Corley Brigman Oct 06 '14 at 15:05
  • btw, you are right... in the class `A`, a function object `f` is created which points to the code defined in the class. so both `a` and `b` get a reference to the _same_ function. you can prove this with `id(a.f)` and `id(b.f)`... – Corley Brigman Oct 06 '14 at 15:07
  • 1
    think you are hitting some weird low-level behaviours there... if you actually print `id(a.f)` and `id(b.f)`, you can clearly see they are the same. also `id(a.f) == id(b.f)` returns `True`. but, `id(id(a.f))` and `id(id(b.f))` return two different numbers, which is why the `is` comparison is failing. – Corley Brigman Oct 06 '14 at 15:16
  • @CorleyBrigman: Sorry my previous comment is a typo, I will erase it – usual me Oct 06 '14 at 15:21
  • @CorleyBrigman: I meant that `a.f is b.f` returns `False`. This is why I used the default mutable argument approach. – usual me Oct 06 '14 at 15:22
  • you're right... that is strange, but what i wrote is still true... the ids of the two are the same, and an equality test on the equals shows they are equal. not sure why the 'is' test returns false... there are lots of strange behaviours here though.. e.g. `id(A.f); id(b.f); id(A.f)` shows a different id the second time, when clearly it can't be... i don't know enough under the hood to know why this happens though. note: that doesn't happen every time, but if you keep trying a mix of ids of A.f, a.f, b.f you can see them change... – Corley Brigman Oct 06 '14 at 15:32
  • It doesn't intuitively make sense that A.f, a.f, and b.f would be the same object at all. A.f is an unbound function, while both a.f and b.f are methods bound to different instances. I think what this boils down to is that when you try to look behind the curtain, the wizard falls over. – Silas Ray Oct 06 '14 at 15:45
  • `A.f` is one callable, a function which takes 3 arguments `self`, `x`, and `d`. `a.f` is a bound method, another callable which takes 2 arguments `x` and `d` (`self` has been bound to `a`, as if `a.f = partial(A.f, a)`), and `b.f` is a third callable with `self` bound to `b` instead. – chepner Oct 06 '14 at 17:03
  • 1
    More precisely (in Python 2.x), `A.f`, `a.f`, and `b.f` are all distinct objects, but `A.f.__func__`, `a.f.__func_`, and `b.f.__func__` are all three the same object (that is, the unbound method and the two bound methods share the same underlying function object). The default value for `d` is "attached" to the function object, not any of the three methods. The same is true in Python 3, except `A.f` is a plain function, not an "unbound method", and `a.f.__func__ is A.f` is true. – chepner Oct 06 '14 at 17:18

0 Answers0