Difference between @classmethod and a method in python
This question already has an answer here:
Let's assume you have a class Car
which represents the Car
entity within your system.
A classmethod
is a method that works for the class Car
not on one of any of Car
's instances. The first parameter to a function decorated with @classmethod
, usually called cls
, is therefore the class itself. Example:
class Car(object):
colour = 'red'
@classmethod
def blue_cars(cls):
# cls is the Car class
# return all blue cars by looping over cls instances
A function acts on a particular instance of the class; the first parameter usually called self
is the instance itself:
def get_colour(self):
return self.colour
To sum up:
use classmethod
to implement methods that work on a whole class (and not on particular class instances):
Car.blue_cars()
use instance methods to implement methods that work on a particular instance:
my_car = Car(colour='red')
my_car.get_colour() # should return 'red'
If you define a method inside a class, it is handled in a special way: access to it wraps it in a special object which modifies the calling arguments in order to include self
, a reference to the referred object:
class A(object):
def f(self):
pass
a = A()
a.f()
This call to af
actually asks f
(via the descriptor protocol) for an object to really return. This object is then called without arguments and deflects the call to the real f
, adding a
in front.
So what af()
really does is calling the original f
function with (a)
as arguments.
In order to prevent this, we can wrap the function
@staticmethod
decorator, @classmethod
decorator, @staticmethod
turns it into an object which, when asked, changes the argument-passing behaviour so that it matches the intentions about calling the original f
:
class A(object):
def method(self):
pass
@staticmethod
def stmethod():
pass
@classmethod
def clmethod(cls):
pass
a = A()
a.method() # the "function inside" gets told about a
A.method() # doesn't work because there is no reference to the needed object
a.clmethod() # the "function inside" gets told about a's class, A
A.clmethod() # works as well, because we only need the classgets told about a's class, A
a.stmethod() # the "function inside" gets told nothing about anything
A.stmethod() # works as well
So @classmethod
and @staticmethod
have in common that they "don't care about" the concrete object they were called with; the difference is that @staticmethod
doesn't want to know anything at all about it, while @classmethod
wants to know its class.
So the latter gets the class object the used object is an instance of. Just replace self
with cls
in this case.
Now, when to use what?
Well, that is easy to handle:
self
, you clearly need an instance method. self
, but want to know about its class, use @classmethod
. This may for example be the case with factory methods. datetime.datetime.now()
is such an example: you can call it via its class or via an instance, but it creates a new instance with completely different data. I even used them once for automatically generating subclasses of a given class. self
nor cls
, you use @staticmethod
. This can as well be used for factory methods, if they don't need to care about subclassing. @classmethod
takes the class as first argument while function takes instance of the class
>>> class Test(object):
... def func(self):
... print self
... @classmethod
... def meth(self):
... print self
>>> t = Test()
>>> t.func()
<__main__.Test object at 0x00000000027238D0>
>>> t.meth()
<class '__main__.Test'>
I've used self
argument in meth
intentionally so it would be very close in syntax to the func
. But usually you'd better use cls
as argument:
... @classmethod
... def meth(cls):
... print cls
链接地址: http://www.djcxy.com/p/9208.html
上一篇: 在C#中完成/处理模式