3

In python, staticmethods are "just functions", and I can refer to them in two different ways:

>>> class A:
...     @staticmethod
...     def f():
...         pass
... 
>>> a=A()
>>> A.f
<function A.f at 0x7f20f8cd3f28>
>>> a.f
<function A.f at 0x7f20f8cd3f28>
>>> a.f is A.f
True

Both a.f and A.f are names that refer to the same object, which happens to be "just a function". Great.

Now, say I have a classmethod:

>>> class B:
...     @classmethod
...     def f(cls):
...         pass
... 
>>> b=B()
>>> b.f is B.f
False

I know that b.f and B.f are not functions: they're bound mothods. This means that the cls argument is implicit, and is always equal to B. Because of this, I would understand that if B2 is a subclass of B, B2().f is B().f would be false, because they're bound methods with different cls arguments. But I don't understand why B().f is B.f yields False. Shouldn't they be the same object, just like A().f and A.f?

EDIT: This question is not the same as "What is the difference between @staticmethod and @classmethod in Python?". I know the difference between staticmethod and classmethod. I want to know one specific thing, which is not addressed in the "umbrella" question linked.

Community
  • 1
  • 1
fonini
  • 2,989
  • 3
  • 21
  • 39
  • A class is like a definition. The `instance` is an actual use of that definition. So the `class` is a recipe, and the `instance` is the cake. Since the recipe is not the cake, and only the instructions on how to make a cake, they are not the same. – RattleyCooper Apr 22 '16 at 20:05
  • @DuckPuncher did you read the body of my question? I want to know why `B().f is B.f` is false and `A().f is A.f` is true. – fonini Apr 22 '16 at 20:07
  • 1
    See also, "User-defined methods" here: https://docs.python.org/2/reference/datamodel.html#types – Robᵩ Apr 22 '16 at 20:20

1 Answers1

4

B().f and B.f are different objects because Python creates a new bound method object each time you refer to a non-static method via attribute access.

For example, B.f is B.f is also False.

>>> B.f is B.f
False

Similarly, you will get a new method object even if the instance stays the same:

>>> b = B()
>>> b.f is b.f
False

@staticmethod creates a new static method object, but

When a static method object is retrieved from a class or a class instance, the object actually returned is the wrapped object, which is not subject to any further transformation.

(from Data model)

In this case A.f always returns the same f function object.

vaultah
  • 44,105
  • 12
  • 114
  • 143