Is it bad form to call a classmethod as a method from an instance?

Question:

Ex.

If I have something like this:

class C(object):
    @classmethod
    def f(cls, x):
       return x + x

This will work:

c = C()

c.f(2)
4

But is that bad form?
Should I only call

C.f()

or

c.__class__.f()

Obviously, this would only make sense in cases where f doesn’t interact with self/cls expecting it to be class.

?

Asked By: Josh Gibson

||

Answers:

It’s mainly just confusing looking. If I were using your class and saw this, it would make me wonder what other surprises are in there, it just looks like bad design.

Is there a reason it’s not just a staticmethod?

Answered By: Trey Stout

C.f() is clearer than c_instance.f(), and c_instance.__class__.f() is just ugly. Since clarity and beauty are dearly loved characteristics in the python community, I’d tend to say that C.f() is the best route.

Is there any particular reason you even want to call it in either of the other ways?

Answered By: vezult

If you have an instance of C already, why do you need f() to be a class method? Not only is it bad form, its usually not necessary. Someone on the net says: “This is bad because it creates the impression that some instance variables in the object are used, but this isn’t the case.”

Although, page 484 of learning python notes that you can call the method either way and it will be exactly the same as long as you pass the same instance in.

Answered By: John Ellinwood

I don’t recall using a classmethod like this from outside the class, but it is certainly ok for an instance method to call a classmethod on itself (e.g. self.foo() where foo is a classmethod). This makes sure that inheritance acts as expected, and will call .foo() in the right subclass instead of the base class.

Answered By: Matt Good

If you are tempted to call a class method from an instance you probably don’t need a class method.

In the example you gave a static method would be more appropriate precisely because of your last remark (no self/cls interaction).

class C(object):
    @staticmethod
    def f(x):
       return x + x

this way it’s “good form” to do both

c = C()
c.f(2)

and

C.f(2)
Answered By: Toni Ruža

I came across this where I was calling some classmethods (that need to be classmethods so that I still have reference to the class) from a non-classmethod, like the following.

class A:
  def a(self, number):
    print("a", self, number)
    self.b(number)

  @classmethod
  def b(cls, number):
    print("b", cls, number + 1)
    cls.c(number)

  @classmethod
  def c(cls, number):
    print("c", cls, number * 2)



b = A()
b.a(3) 

The above code produces the following result:

a <__main__.A object at 0x000001FAC09FE358> 3
b <class '__main__.A'> 4
c <class '__main__.A'> 6

I’m not saying that it’s the best convention, but it doesn’t break anything in Python 3.6

Answered By: David Culbreth
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.