2

Please take a look at code, you will get whole message what I am trying to convey.

class Foo:
   def fun(self):
       pass

a = Foo.fun
print "a is Foo.fun: %s" % (a is Foo.fun)

b = a
c = Foo.fun

print "b is c", (b is c)
print "c is Foo.fun", (c is Foo.fun)

def barFun():
   pass

bar = barFun
print "bar is barFun", (bar is barFun)

OutPut:

a is Foo.fun: False
b is c False
c is Foo.fun False
bar is barFun True

Here, why the variable a is not referring Foo.fun. As I know variable assignment is like increasing reference count. i.e, new variable will start pointing the object unlike in language c. So, as we are assigning Foo.fun to var a, a and Foo.fun both should point same object in the memory. But results are unexpected. While this assignment works well with normal function.

Here is the code id's of objects are different for unbound method assignment.

class Foo:
   def fun(self):
       pass

a = Foo.fun
print "Id of a: %s. Id of Foo.fun: %s" % (id(a), id(Foo.fun))

b = a
c = Foo.fun

print "Id of b: %s. Id of c: %s" % (id(b), id(c))
print "Id of c: %s. Id of  Foo.fun: %s" % (id(c), id(Foo.fun))

def barFun():
   pass

bar = barFun
print "Id of bar: %s. Id of barFun: %s" % (id(bar), id(barFun))

OutPut:

Id of a: 10155824. Id of Foo.fun: 139916772374320
Id of b: 10155824. Id of c: 139916772374320
Id of c: 139916772374320. Id of  Foo.fun: 10156224
Id of bar: 10741352. Id of barFun: 10741352
neotam
  • 2,611
  • 1
  • 31
  • 53
  • 1
    This is indeed unusual behavior, but it is at least somewhat [documented](https://docs.python.org/3/reference/expressions.html#id19). My practical recommendation is to not worry about it too much, and write code that doesn't depend heavily on the implementation details of `is` or `id`. – Kevin Oct 29 '15 at 19:45
  • 2
    Because when you access `ClassName.method_name` you get a new unbound method object. – jonrsharpe Oct 29 '15 at 19:45
  • Recommended reading: [python bound and unbound method object](http://stackoverflow.com/q/13348031/953482) – Kevin Oct 29 '15 at 19:58

1 Answers1

0

In python 2, Foo.fun is what's called an "unbound method." All methods, bound and unbound, are created dynamically every time you call Foo.fun or Foo().fun so a new method object is created on every call.

In python 3 the idea of "unbound methods" is dropped and Foo.fun simply returns a function. In this case, you'll get the behavior you expect. (Foo().fun still returns a method object in python 3.)

Bi Rico
  • 25,283
  • 3
  • 52
  • 75