Maybe a bit of example code will help: Notice the difference in the call signatures of foo
, class_foo
and static_foo
:
class A(object):
def foo(self, x):
print(f"executing foo({self}, {x})")
@classmethod
def class_foo(cls, x):
print(f"executing class_foo({cls}, {x})")
@staticmethod
def static_foo(x):
print(f"executing static_foo({x})")
a = A()
Below is the usual way an object instance calls a method. The object instance, a
, is implicitly passed as the first argument.
a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>, 1)
With classmethods, the class of the object instance is implicitly passed as the first argument instead of self
.
a.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)
You can also call class_foo
using the class. In fact, if you define something to be
a classmethod, it is probably because you intend to call it from the class rather than from a class instance. A.foo(1)
would have raised a TypeError, but A.class_foo(1)
works just fine:
A.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)
One use people have found for class methods is to create inheritable alternative constructors.
With staticmethods, neither self
(the object instance) nor cls
(the class) is implicitly passed as the first argument. They behave like plain functions except that you can call them from an instance or the class:
a.static_foo(1)
# executing static_foo(1)
A.static_foo('hi')
# executing static_foo(hi)
Staticmethods are used to group functions which have some logical connection with a class to the class.
foo
is just a function, but when you call a.foo
you don't just get the function,
you get a "partially applied" version of the function with the object instance a
bound as the first argument to the function. foo
expects 2 arguments, while a.foo
only expects 1 argument.
a
is bound to foo
. That is what is meant by the term "bound" below:
print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
With a.class_foo
, a
is not bound to class_foo
, rather the class A
is bound to class_foo
.
print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>
Here, with a staticmethod, even though it is a method, a.static_foo
just returns
a good 'ole function with no arguments bound. static_foo
expects 1 argument, and
a.static_foo
expects 1 argument too.
print(a.static_foo)
# <function static_foo at 0xb7d479cc>
And of course the same thing happens when you call static_foo
with the class A
instead.
print(A.static_foo)
# <function static_foo at 0xb7d479cc>
Best Answer
Jim has got this pretty much covered in his blog post, but I'm posting a briefing here for reference.
First, let's see what the Scala Specification tell us. Chapter 3 (types) tell us about Function Types (3.2.9) and Method Types (3.3.1). Chapter 4 (basic declarations) speaks of Value Declaration and Definitions (4.1), Variable Declaration and Definitions (4.2) and Functions Declarations and Definitions (4.6). Chapter 6 (expressions) speaks of Anonymous Functions (6.23) and Method Values (6.7). Curiously, function values is spoken of one time on 3.2.9, and no where else.
A Function Type is (roughly) a type of the form (T1, ..., Tn) => U, which is a shorthand for the trait
FunctionN
in the standard library. Anonymous Functions and Method Values have function types, and function types can be used as part of value, variable and function declarations and definitions. In fact, it can be part of a method type.A Method Type is a non-value type. That means there is no value - no object, no instance - with a method type. As mentioned above, a Method Value actually has a Function Type. A method type is a
def
declaration - everything about adef
except its body.Value Declarations and Definitions and Variable Declarations and Definitions are
val
andvar
declarations, including both type and value - which can be, respectively, Function Type and Anonymous Functions or Method Values. Note that, on the JVM, these (method values) are implemented with what Java calls "methods".A Function Declaration is a
def
declaration, including type and body. The type part is the Method Type, and the body is an expression or a block. This is also implemented on the JVM with what Java calls "methods".Finally, an Anonymous Function is an instance of a Function Type (ie, an instance of the trait
FunctionN
), and a Method Value is the same thing! The distinction is that a Method Value is created from methods, either by postfixing an underscore (m _
is a method value corresponding to the "function declaration" (def
)m
), or by a process called eta-expansion, which is like an automatic cast from method to function.That is what the specs say, so let me put this up-front: we do not use that terminology! It leads to too much confusion between so-called "function declaration", which is a part of the program (chapter 4 -- basic declarations) and "anonymous function", which is an expression, and "function type", which is, well a type -- a trait.
The terminology below, and used by experienced Scala programmers, makes one change from the terminology of the specification: instead of saying function declaration, we say method. Or even method declaration. Furthermore, we note that value declarations and variable declarations are also methods for practical purposes.
So, given the above change in terminology, here's a practical explanation of the distinction.
A function is an object that includes one of the
FunctionX
traits, such asFunction0
,Function1
,Function2
, etc. It might be includingPartialFunction
as well, which actually extendsFunction1
.Let's see the type signature for one of these traits:
This trait has one abstract method (it has a few concrete methods as well):
And that tell us all that there is to know about it. A function has an
apply
method which receives N parameters of types T1, T2, ..., TN, and returns something of typeR
. It is contra-variant on the parameters it receives, and co-variant on the result.That variance means that a
Function1[Seq[T], String]
is a subtype ofFunction1[List[T], AnyRef]
. Being a subtype means it can be used in place of it. One can easily see that if I'm going to callf(List(1, 2, 3))
and expect anAnyRef
back, either of the two types above would work.Now, what is the similarity of a method and a function? Well, if
f
is a function andm
is a method local to the scope, then both can be called like this:These calls are actually different, because the first one is just a syntactic sugar. Scala expands it to:
Which, of course, is a method call on object
f
. Functions also have other syntactic sugars to its advantage: function literals (two of them, actually) and(T1, T2) => R
type signatures. For example:Another similarity between a method and a function is that the former can be easily converted into the latter:
Scala will expand that, assuming
m
type is(List[Int])AnyRef
into (Scala 2.7):On Scala 2.8, it actually uses an
AbstractFunction1
class to reduce class sizes.Notice that one can't convert the other way around -- from a function to a method.
Methods, however, have one big advantage (well, two -- they can be slightly faster): they can receive type parameters. For instance, while
f
above can necessarily specify the type ofList
it receives (List[Int]
in the example),m
can parameterize it:I think this pretty much covers everything, but I'll be happy to complement this with answers to any questions that may remain.