问题
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.
?
回答1:
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)
回答2:
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.
回答3:
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?
回答4:
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?
回答5:
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.
回答6:
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
来源:https://stackoverflow.com/questions/692040/is-it-bad-form-to-call-a-classmethod-as-a-method-from-an-instance