They are wrong. But, it's a minor confusion they made and doing video courses which involves speaking and typing can be certainly challenging. No big deal.
When the function belongs to a class, it's a method (a more specialized form of a function). When it's outside of a class it's a function.
How do I know they are wrong?
You use this syntax to create one in Python:
class SomeClass:
@classmethod
def the_method(cls, vars):
....
def instance_method(self, vars):
...
It's not a @classfunction decorator. It's a @classmethod decorator.
See the docs at https://docs.python.org/3/library/functions.html#classmethod
Answer from Michael Kennedy on Stack OverflowThey are wrong. But, it's a minor confusion they made and doing video courses which involves speaking and typing can be certainly challenging. No big deal.
When the function belongs to a class, it's a method (a more specialized form of a function). When it's outside of a class it's a function.
How do I know they are wrong?
You use this syntax to create one in Python:
class SomeClass:
@classmethod
def the_method(cls, vars):
....
def instance_method(self, vars):
...
It's not a @classfunction decorator. It's a @classmethod decorator.
See the docs at https://docs.python.org/3/library/functions.html#classmethod
Method is the correct term for a function in a class. Methods and functions are pretty similar to each other. The only difference is that a method is called with an object and has the possibility to modify data of an object. Functions can modify and return data but they dont have an impact on objects.
Edit : Class function and method both mean the same thing although saying class function is not the right way to say it.
Videos
What is the main difference between a function and a method in Python?
What are class methods and static methods, and when should I use them?
Why would one use methods instead of functions?
Create a function. Functions do specific things, classes are specific things.
Classes often have methods, which are functions that are associated with a particular class, and do things associated with the thing that the class is - but if all you want is to do something, a function is all you need.
Essentially, a class is a way of grouping functions (as methods) and data (as properties) into a logical unit revolving around a certain kind of thing. If you don't need that grouping, there's no need to make a class.
Like what Amber says in her answer: create a function. In fact when you don't have to make classes if you have something like:
class Person(object):
def __init__(self, arg1, arg2):
self.arg1 = arg1
self.arg2 = arg2
def compute(self, other):
""" Example of bad class design, don't care about the result """
return self.arg1 + self.arg2 % other
Here you just have a function encapsulate in a class. This just make the code less readable and less efficient. In fact the function compute can be written just like this:
def compute(arg1, arg2, other):
return arg1 + arg2 % other
You should use classes only if you have more than 1 function to it and if keep a internal state (with attributes) has sense. Otherwise, if you want to regroup functions, just create a module in a new .py file.
You might look this video (Youtube, about 30min), which explains my point. Jack Diederich shows why classes are evil in that case and why it's such a bad design, especially in things like API.
It's quite a long video but it's a must see.
Title. I’m having a hard time understanding the differences.
I am new to python and object oriented programming in general, and so far, one thing I struggle with is when to define a method for a class vs a general function callable by any object (e.g. object.method() vs method(object)). It seems to me that the general rule is if different classes require a different algorithm to be called, then it makes sense to define it as a class method so that the switching will happen automatically by class and the code will be much cleaner. Is that the basic idea? Or is it more related to whether the default argument is going to be "self" anyway?
Also, in terms of when to define classes in general, it seems to me that if one variable name should hold many different fields (and those fields are desired to be able to be changed), then it is a good idea to make a class. Does that sound right?
Any other advice would be appreciated,
Hi! I have very less time working with python and now I am going through classes, but until now they look kind of similar to definition of functions. When should I use one and when another? Is there a clear example for it?
Thanks a lot!
Yes. To be clear, methods are functions, they are simply attached to the class, and when that function is called from an instance it gets that instance passed implicitly as the first argument automagically*. It doesn't actually matter where that function is defined. Consider:
class FooBar:
def __init__(self, n):
self.n = n
def foo(self):
return '|'.join(self.n*['foo'])
fb = FooBar(2)
print(fb.foo())
def bar(self):
return '*'.join(self.n*['bar'])
print(bar(fb))
FooBar.bar = bar
print(fb.bar())
*I highly recommend reading the descriptor HOWTO. Spoiler alert, Functions are descriptors. This is how Python magically passes instances to methods (that is, all function objects are descriptors who's __get__ method passes the instance as the first argument to the function itself when accessed by an instance on a class!. The HOWTO shows Python implementations of all of these things, including how you could implement property in pure Python!
Actually, methods and functions in Python are exactly the same thing!
It matters not one bit where it is defined. What matters is how it is looked up.
def defined_outside(*args):
return args
class C:
def defined_inside(*args):
return args
C.defined_outside = defined_outside
defined_inside = C.defined_inside
instance = C()
print( defined_inside (1,2))
print( defined_outside(1,2))
print(instance.defined_inside (1,2))
print(instance.defined_outside(1,2))
which gives the output
(1, 2)
(1, 2)
(<__main__.C object at 0x7f0c80d417f0>, 1, 2)
(<__main__.C object at 0x7f0c80d417f0>, 1, 2)
(This will only work in Python 3: Two of these will produce a TypeError in Python 2.)
What is important to notice about the output is that, in the first two cases, the functions receive two arguments: 1 and 2. In the last two cases they receive three arguments: instance, 1 and 2.
In the cases where instance is passed to the function, the function is behaving like a method. In the cases where instance is not passed in, the function is behaving like a plain function. But notice that both behaviours are exhibited by both the function which was defined inside the classe and the one which was defined outside the class.
What matters is how the function was looked up. If it was looked up as an attribute of an instance of a class, then the function behaves like a method; otherwise it behaves like a free function.
[Incidentally, this binding behaviour only works for pure Python functions; it does not work for functions defined using the Python/C API. The latter always behave like functions and never like methods:
C.dir = dir
instance.dir()
will give you a directory of the global scope, not of instance, indicating that dir recived zero arguments, rather that receiving instance as an argument.
]
If your method calls a static method on the class, then it does require information on the class. You have a class method, not a static method. By declaring it @classmethod (and adding the cls parameter), you not only properly inform the reader, you allow polymorphism. An inheritor can reimplement the called static method and change behavior.
Python's static methods are intended for methods that are part of a class, and can be called as either a class method or an instance method: both Class.the_method() and self.the_method() would work. When the static method is called, it is not given an implicit first argument:
class Example:
def instance_method_example(self, arguments):
...
@classmethod
def class_method_example(cls, arguments):
...
@staticmethod
def static_method_example(arguments):
...
If you merely want to create a helper function that is used within your class, do not use @staticmethod. Define a free function outside of the class. For example:
class Example:
def some_method(self, argument):
return _helper(argument, self.x)
def _helper(a, b):
...
The background of static methods in Python is the following: when you access an attribute of an object x.attribute or getattr(x, 'attribute'), then this name is looked up in the instance dict or the class dict. If an object is found in the class dict, it is checked whether that object is a “descriptor”: an object that describes how this attribute behaves, not an object that would be directly returned. Descriptors have dunder-methods like __get__, __set__, and __del__ that are invoked depending on whether the descriptor is accessed, assigned to, or deleted with the del operator.
Functions – the things you declare with def – are descriptors. By default, the __get__ descriptor binds the function to the instance argument (typically called self) and returns the bound function, so that it can be invoked as a method. But the various decorators change this behaviour:
- a
@classmethod defbinds to the class object, not the instance - a
@staticmethod defdoes not bind to any object and just returns the underlying function directly - a
@propertyinvokes the underlying function to retrieve a value
These differences are (partially) visible when looking at the repr() of the bound methods. With the first Example class:
instance_method_example- with class:
Example.instance_method_example
is<function Example.instance_method_example at 0x7f1dfdd6fd30>,
the unbound function - with instance:
<function Example.instance_method_example at 0x7f1dfdd6fd30>
is<bound method Example.instance_method_example of <__main__.Example object at 0x7f1dfdddcb80>>,
a method bound to the instance
- with class:
class_method_example- with class:
Example.class_method_example
is<bound method Example.class_method_example of <class '__main__.Example'>>,
a method bound to the class - with instance:
Example().class_method_example
is<bound method Example.class_method_example of <class '__main__.Example'>>,
also a method bound to the class
- with class:
static_method_example- with class:
Example.static_method_example
is<function Example.static_method_example at 0x7f1dfdd6fe50>,
the unbound function - with instance:
Example().static_method_example
is<function Example.static_method_example at 0x7f1dfdd6fe50>,
also the unbound function
- with class:
As a table:
| invoked on… | no decorator | @classmethod |
@staticmethod |
|---|---|---|---|
| … instance | bound to instance | bound to class | unbound |
| … class | unbound | bound to class | unbound |