Is it bad form to call a classmethod as a method f

2020-03-01 04:12发布

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.

?

6条回答
迷人小祖宗
2楼-- · 2020-03-01 04:19

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.

查看更多
相关推荐>>
3楼-- · 2020-03-01 04:23

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

查看更多
虎瘦雄心在
4楼-- · 2020-03-01 04:26

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?

查看更多
不美不萌又怎样
5楼-- · 2020-03-01 04:29

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)
查看更多
虎瘦雄心在
6楼-- · 2020-03-01 04:37

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.

查看更多
贪生不怕死
7楼-- · 2020-03-01 04:37

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?

查看更多
登录 后发表回答