Assuming I have a class which requires a function (or should I say method) which is:
independent from my class instance - doesn't need self argument;
is called only inside my class object
I won't need access to it at any point (to override it for example);
should I (A) place it inside the class and mark it as a #staticmethod or should I (B) define it outside my class object (but in the same namespace)? Why?
Example:
class A:
def __init__(self, my_int):
self.my_int = my_int
def my_int_and_4(self):
print(self.adder(self.my_int,4))
#staticmethod
def adder(a,b):
return a+b
or
def adder(a,b):
return a+b
class B:
def __init__(self, my_int):
self.my_int = my_int
def my_int_and_4(self):
print(adder(self.my_int,4))
EDIT: maybe the example is a bit oversimplified. I should have added that my version of "adder" is specificly used with my class and in no other case.
This is a textbook use case for a private static method.
They key point here is that you should make it a private method of that class. That way you're certain nothing else will use it and depend on its implementation. You'll be free to change it in the future, or even delete it, without breaking anything outside that class.
And yeah, make it static, because you can.
In Python, there is no way to make a method truly private, but by convention, prefixing the method name by a _ means it should be treated as private.
#staticmethod
def _adder(a,b): ## <-- note the _
return a+b
If at some point you suddenly need to use it outside the class, then exposing it will be no trouble at all, e.g. using a public wrapper method.
The reverse, however, isn't true; once exposed, it's difficult to retract that exposure.
I would definitely use a private static method in this case, for the reasons described by Jean-Francois Corbett. There are two types of methods in Python that belong to the class itself, rather than an instance: class methods and static methods.
The first parameter of a class method (created with #classmethod) references the class in exactly the same manner that the first parameter of an instance method (self) references an instance. It is the equivalent of static methods in most other languages. If your method requires access to other class members, use a class method.
A static method (created with #staticmethod) does not contain a reference to the class, and therefore cannot reference other class members. It's generally used for private helper methods and the like.
For your adder method, I would definitely use a static method. However, in this modified (and rather useless) version, a class method is necessary:
class A:
x = 1
def __init__(self, my_int):
self.my_int = my_int
def my_int_and_4(self):
print(self._adder(self.my_int,4))
#staticmethod
def _adder(a,b):
return a+b
#classmethod
def _increment(cls, n):
return n + cls.x
Both approaches will work, so it's the matter of readability and following conventions.
Does the method need to look at the instance's private attributes? If yes, it's a good reason to keep it in the class.
Is the method only used as a helper for one of different methods? If yes, it's a good reason to put it right after the calling method so that the code can be read top-down.
Does the method seem to make sense outside of the context of your class? If yes, it's a good reason to make it a free function or even move it to a different file, like utils.
Related
This question already has answers here:
Difference between #staticmethod and #classmethod
(35 answers)
Why do we use #staticmethod?
(4 answers)
Closed last month.
I ran into unbound method error in python with this code:
import random
class Sample(object):
def drawSample(samplesize, List):
sample = random.sample(List, samplesize)
return sample
Choices=range(100)
print(Sample.drawSample(5, Choices))
I was able to fix the problem by adding #staticmethod to the method. However, I don't really understand the situation.
What is the point of using "static" methods? Why does it solve the problem in this code, and why are they ever necessary? Conversely, why would I ever not want to do it (i.e., why is extra code needed to make the method static)?
See this article for detailed explanation.
TL;DR
1.It eliminates the use of self argument.
2.It reduces memory usage because Python doesn't have to instantiate a bound-method for each object instiantiated:
>>>RandomClass().regular_method is RandomClass().regular_method
False
>>>RandomClass().static_method is RandomClass().static_method
True
>>>RandomClass.static_method is RandomClass().static_method
True
3.It improves code readability, signifying that the method does not depend on state of the object itself.
4.It allows for method overriding in that if the method were defined at the module-level (i.e. outside the class) a subclass would not be able to override that method.
Static methods have limited use, because they don't have access to the attributes of an instance of a class (like a regular method does), and they don't have access to the attributes of the class itself (like a class method does).
So they aren't useful for day-to-day methods.
However, they can be useful to group some utility function together with a class - e.g. a simple conversion from one type to another - that doesn't need access to any information apart from the parameters provided (and perhaps some attributes global to the module.)
They could be put outside the class, but grouping them inside the class may make sense where they are only applicable there.
You can also reference the method via an instance or the class, rather than the module name, which may help the reader understand to what instance the method is related.
This is not quite to the point of your actual question, but since you've said you are a python newbie perhaps it will be helpful, and no one else has quite come out and said it explicitly.
I would never have fixed the above code by making the method a static method. I would either have ditched the class and just written a function:
def drawSample(samplesize,List):
sample=random.sample(List,samplesize)
return sample
Choices=range(100)
print drawSample(5,Choices)
If you have many related functions, you can group them in a module - i.e, put them all in the same file, named sample.py for example; then
import sample
Choices=range(100)
print sample.drawSample(5,Choices)
Or I would have added an __init__ method to the class and created an instance that had useful methods:
class Sample(object):
'''This class defines various methods related to the sample'''
def __init__(self, thelist):
self.list = thelist
def draw_sample(self, samplesize):
sample=random.sample(self.list,samplesize)
return sample
choices=Sample(range(100))
print choices.draw_sample(5)
(I also changed the case conventions in the above example to match the style recommended by PEP 8.)
One of the advantages of Python is that it doesn't force you to use classes for everything. You can use them only when there is data or state that should be associated with the methods, which is what classes are for. Otherwise you can use functions, which is what functions are for.
Why one would want to define static methods?
Suppose we have a class called Math then
nobody will want to create object of class Math
and then invoke methods like ceil and floor and fabs on it.
So we make them static.
For example doing
>> Math.floor(3.14)
is much better than
>> mymath = Math()
>> mymath.floor(3.14)
So they are useful in some way. You need not create an instance of a class to use them.
Why are not all methods defined as static methods?
They don't have access to instance variables.
class Foo(object):
def __init__(self):
self.bar = 'bar'
def too(self):
print self.bar
#staticmethod
def foo():
print self.bar
Foo().too() # works
Foo.foo() # doesn't work
That is why we don't make all the methods static.
The alternatives to a staticmethod are: classmethod, instancemethod, and function. If you don't know what these are, scroll down to the last section. If a staticmethod is better than any of these alternatives, depends on for what purpose it is written.
advantages of the Python static method
If you don't need access to the attributes or methods of the class or instance, a staticmethod is better than a classmethod or instancemethod. That way it is clear (from the #staticmethod decorator) that the class' and instance's state is not read or modified. However, using a function makes that distinction even clearer (see disadvantages).
The call signature of a staticmethod is the same as that of a classmethod or instancemethod, namely <instance>.<method>(<arguments>). Hence it can easily be replaced by one of the three if that is needed later on or in a derived class. You can't do that with a simple function.
A staticmethod can be used instead of a function to make clear that it subjectively belongs to a class and to prevent namespace conflicts.
disadvantages of the Python static method
It cannot access attributes or methods of the instance or class.
The call signature of a staticmethod is the same as that of a classmethod or instancemethod. This masks the fact that the staticmethod does not actually read or modify any object information. This makes code harder to read. Why not just use a function?
A staticmethod is difficult to re-use if you ever need to call it from outside the class/instance where it was defined. If there is any potential for re-use, a function is the better choice.
The staticmethod is seldom used, so people reading code that includes one may take a little longer to read it.
alternatives to a static method in Python
To address discuss the advantages of the staticmethod, we need to know what the alternatives are and how they differ from each other.
The staticmethod belongs to a class but cannot access or modify any instance or class information.
There are three alternatives to it:
The classmethod has access to the caller's class.
The instancemethod has access to the caller's instance and its class.
The function has nothing to do with classes. It is the closest in capability to the staticmethod.
Here's what this looks like in code:
# function
# has nothing to do with a class
def make_cat_noise(asker_name):
print('Hi %s, mieets mieets!' % asker_name)
# Yey, we can make cat noises before we've even defined what a cat is!
make_cat_noise('JOey') # just a function
class Cat:
number_of_legs = 4
# special instance method __init__
def __init__(self, name):
self.name = name
# instancemethod
# the instance (e.g. Cat('Kitty')) is passed as the first method argument
def tell_me_about_this_animal(self, asker_name):
print('Hi %s, This cat has %d legs and is called %s'
% (asker_name, self.number_of_legs, self.name))
# classmethod
# the class (e.g. Cat) is passed as the first method argument
# by convention we call that argument cls
#classmethod
def tell_me_about_cats(cls, asker_name):
print("Hi %s, cats have %d legs."
% (asker_name, cls.number_of_legs))
# cls.name # AttributeError because only the instance has .name
# self.name # NameError because self isn't defined in this namespace
# staticmethod
# no information about the class or the instance is passed to the method
#staticmethod
def make_noise(asker_name):
print('Hi %s, meooow!' % asker_name)
# class and instance are not accessible from here
# one more time for fun!
make_cat_noise('JOey') # just a function
# We just need the class to call a classmethod or staticmethod:
Cat.make_noise('JOey') # staticmethod
Cat.tell_me_about_cats('JOey') # classmethod
# Cat.tell_me_about_this_animal('JOey') # instancemethod -> TypeError
# With an instance we can use instancemethod, classmethod or staticmethod
mycat = Cat('Kitty') # mycat is an instance of the class Cat
mycat.make_noise('JOey') # staticmethod
mycat.tell_me_about_cats('JOey') # classmethod
mycat.tell_me_about_this_animal('JOey') # instancemethod
When you call a function object from an object instance, it becomes a 'bound method' and gets the instance object itself is passed in as a first argument.
When you call a classmethod object (which wraps a function object) on an object instance, the class of the instance object gets passed in as a first argument.
When you call a staticmethod object (which wraps a function object), no implicit first argument is used.
class Foo(object):
def bar(*args):
print args
#classmethod
def baaz(*args):
print args
#staticmethod
def quux(*args):
print args
>>> foo = Foo()
>>> Foo.bar(1,2,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got int instance instead)
>>> Foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> Foo.quux(1,2,3)
(1, 2, 3)
>>> foo.bar(1,2,3)
(<Foo object at 0x1004a4510>, 1, 2, 3)
>>> foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> foo.quux(1,2,3)
(1, 2, 3)
static methods are great because you don't have to declare an instance of the object to which the method belongs.
python's site has some great documentation on static methods here:
http://docs.python.org/library/functions.html#staticmethod
In my estimation, there is no single performance benefit of using #staticmethods compared to just defining the function outside of and separate from the class it would otherwise be a #staticmethod of.
The only thing I would say justifies their existence is convenience. Static methods are common in other popular programming languages, so why not python? If you want to create a function with behavior that is very closely associated with the class you are creating it for but it doesn't actually access/modify the internal data of an instance of the class in a way that justifies conceptualizing it as a typical method of that class then slap a #staticmethod above it and anyone reading your code will immediately learn a lot about the nature of the method and its relationship to the class.
One thing I occasionally like to do is place functionality that my class uses internally a lot into private #staticmethods. That way I do not clutter the API exposed by my module with methods that no one using my module would ever need to see let alone use.
Static methods have almost no reason-to-be in Python. You use either instance methods or class methods.
def method(self, args):
self.member = something
#classmethod
def method(cls, args):
cls.member = something
#staticmethod
def method(args):
MyClass.member = something
# The above isn't really working
# if you have a subclass
Because namespacing functions is nice (as was previously pointed out):
When I want to be explicit about methods that don't change the state of the object, I use static methods. This discourages people on my team to start changing the object's attributes in those methods.
When i refactor really rotten code, I start by trying to make as many methods #staticmethod as possible. This allows me then to extract these methods into a class - though I agree, this is rarely something I use, it did came in helpful a few times.
I just can't see why do we need to use #staticmethod. Let's start with an exmaple.
class test1:
def __init__(self,value):
self.value=value
#staticmethod
def static_add_one(value):
return value+1
#property
def new_val(self):
self.value=self.static_add_one(self.value)
return self.value
a=test1(3)
print(a.new_val) ## >>> 4
class test2:
def __init__(self,value):
self.value=value
def static_add_one(self,value):
return value+1
#property
def new_val(self):
self.value=self.static_add_one(self.value)
return self.value
b=test2(3)
print(b.new_val) ## >>> 4
In the example above, the method, static_add_one , in the two classes do not require the instance of the class(self) in calculation.
The method static_add_one in the class test1 is decorated by #staticmethod and work properly.
But at the same time, the method static_add_one in the class test2 which has no #staticmethod decoration also works properly by using a trick that provides a self in the argument but doesn't use it at all.
So what is the benefit of using #staticmethod? Does it improve the performance? Or is it just due to the zen of python which states that "Explicit is better than implicit"?
The reason to use staticmethod is if you have something that could be written as a standalone function (not part of any class), but you want to keep it within the class because it's somehow semantically related to the class. (For instance, it could be a function that doesn't require any information from the class, but whose behavior is specific to the class, so that subclasses might want to override it.) In many cases, it could make just as much sense to write something as a standalone function instead of a staticmethod.
Your example isn't really the same. A key difference is that, even though you don't use self, you still need an instance to call static_add_one --- you can't call it directly on the class with test2.static_add_one(1). So there is a genuine difference in behavior there. The most serious "rival" to a staticmethod isn't a regular method that ignores self, but a standalone function.
Today I suddenly find a benefit of using #staticmethod.
If you created a staticmethod within a class, you don't need to create an instance of the class before using the staticmethod.
For example,
class File1:
def __init__(self, path):
out=self.parse(path)
def parse(self, path):
..parsing works..
return x
class File2:
def __init__(self, path):
out=self.parse(path)
#staticmethod
def parse(path):
..parsing works..
return x
if __name__=='__main__':
path='abc.txt'
File1.parse(path) #TypeError: unbound method parse() ....
File2.parse(path) #Goal!!!!!!!!!!!!!!!!!!!!
Since the method parse is strongly related to the classes File1 and File2, it is more natural to put it inside the class. However, sometimes this parse method may also be used in other classes under some circumstances. If you want to do so using File1, you must create an instance of File1 before calling the method parse. While using staticmethod in the class File2, you may directly call the method by using the syntax File2.parse.
This makes your works more convenient and natural.
I will add something other answers didn't mention. It's not only a matter of modularity, of putting something next to other logically related parts. It's also that the method could be non-static at other point of the hierarchy (i.e. in a subclass or superclass) and thus participate in polymorphism (type based dispatching). So if you put that function outside the class you will be precluding subclasses from effectively overriding it. Now, say you realize you don't need self in function C.f of class C, you have three two options:
Put it outside the class. But we just decided against this.
Do nothing new: while unused, still keep the self parameter.
Declare you are not using the self parameter, while still letting other C methods to call f as self.f, which is required if you wish to keep open the possibility of further overrides of f that do depend on some instance state.
Option 2 demands less conceptual baggage (you already have to know about self and methods-as-bound-functions, because it's the more general case). But you still may prefer to be explicit about self not being using (and the interpreter could even reward you with some optimization, not having to partially apply a function to self). In that case, you pick option 3 and add #staticmethod on top of your function.
Use #staticmethod for methods that don't need to operate on a specific object, but that you still want located in the scope of the class (as opposed to module scope).
Your example in test2.static_add_one wastes its time passing an unused self parameter, but otherwise works the same as test1.static_add_one. Note that this extraneous parameter can't be optimized away.
One example I can think of is in a Django project I have, where a model class represents a database table, and an object of that class represents a record. There are some functions used by the class that are stand-alone and do not need an object to operate on, for example a function that converts a title into a "slug", which is a representation of the title that follows the character set limits imposed by URL syntax. The function that converts a title to a slug is declared as a staticmethod precisely to strongly associate it with the class that uses it.
While integrating a Django app I have not used before, I found two different ways to define functions inside the class. The author seems to use them both distinctively and intentionally. The first one is the one that I myself use a lot:
class Dummy(object):
def some_function(self, *args, **kwargs):
# do something here
# self is the class instance
The other one is the one I never use, mostly because I do not understand when and what to use it for:
class Dummy(object):
#classmethod
def some_function(cls, *args, **kwargs):
# do something here
# cls refers to what?
The classmethod decorator in the python documentation says:
A class method receives the class as the implicit first argument, just
like an instance method receives the instance.
So I guess cls refers to Dummy itself (the class, not the instance). I do not exactly understand why this exists, because I could always do this:
type(self).do_something_with_the_class
Is this just for the sake of clarity, or did I miss the most important part: spooky and fascinating things that couldn't be done without it?
Your guess is correct - you understand how classmethods work.
The why is that these methods can be called both on an instance OR on the class (in both cases, the class object will be passed as the first argument):
class Dummy(object):
#classmethod
def some_function(cls,*args,**kwargs):
print cls
#both of these will have exactly the same effect
Dummy.some_function()
Dummy().some_function()
On the use of these on instances: There are at least two main uses for calling a classmethod on an instance:
self.some_function() will call the version of some_function on the actual type of self, rather than the class in which that call happens to appear (and won't need attention if the class is renamed); and
In cases where some_function is necessary to implement some protocol, but is useful to call on the class object alone.
The difference with staticmethod: There is another way of defining methods that don't access instance data, called staticmethod. That creates a method which does not receive an implicit first argument at all; accordingly it won't be passed any information about the instance or class on which it was called.
In [6]: class Foo(object): some_static = staticmethod(lambda x: x+1)
In [7]: Foo.some_static(1)
Out[7]: 2
In [8]: Foo().some_static(1)
Out[8]: 2
In [9]: class Bar(Foo): some_static = staticmethod(lambda x: x*2)
In [10]: Bar.some_static(1)
Out[10]: 2
In [11]: Bar().some_static(1)
Out[11]: 2
The main use I've found for it is to adapt an existing function (which doesn't expect to receive a self) to be a method on a class (or object).
One of the most common uses of classmethod in Python is factories, which are one of the most efficient methods to build an object. Because classmethods, like staticmethods, do not need the construction of a class instance. (But then if we use staticmethod, we would have to hardcode the instance class name in the function)
This blog does a great job of explaining it:
https://iscinumpy.gitlab.io/post/factory-classmethods-in-python/
If you add decorator #classmethod, That means you are going to make that method as static method of java or C++. ( static method is a general term I guess ;) )
Python also has #staticmethod. and difference between classmethod and staticmethod is whether you can
access to class or static variable using argument or classname itself.
class TestMethod(object):
cls_var = 1
#classmethod
def class_method(cls):
cls.cls_var += 1
print cls.cls_var
#staticmethod
def static_method():
TestMethod.cls_var += 1
print TestMethod.cls_var
#call each method from class itself.
TestMethod.class_method()
TestMethod.static_method()
#construct instances
testMethodInst1 = TestMethod()
testMethodInst2 = TestMethod()
#call each method from instances
testMethodInst1.class_method()
testMethodInst2.static_method()
all those classes increase cls.cls_var by 1 and print it.
And every classes using same name on same scope or instances constructed with these class is going to share those methods.
There's only one TestMethod.cls_var
and also there's only one TestMethod.class_method() , TestMethod.static_method()
And important question. why these method would be needed.
classmethod or staticmethod is useful when you make that class as a factory
or when you have to initialize your class only once. like open file once, and using feed method to read the file line by line.
Look at this code:
class MyClass():
# Why does this give me "NameError: name 'self' is not defined":
mySelf = self
# But this does not?
def myFunction(self):
mySelf2 = self
Basically I want a way for a class to refer to itself without needing to name itself specifically, hence I want self to work for the class, not just methods/functions. How can I achieve this?
EDIT: The point of this is that I'm trying to refer to the class name from inside the class itself with something like self.class._name_ so that the class name isn't hardcoded anywhere in the class's code, and thus it's easier to re-use the code.
EDIT 2: From what I've learned from the answers below, what I'm trying to do is impossible. I'll have to find a different way. Mission abandoned.
EDIT 3: Here is specifically what I'm trying to do:
class simpleObject(object):
def __init__(self, request):
self.request = request
#view_defaults(renderer='string')
class Test(simpleObject):
# this line throws an error because of self
myClassName = self.__class__.__name__
#view_config(route_name=myClassName)
def activateTheView(self):
db = self.request.db
foo = 'bar'
return foo
Note that self is not defined at the time when you want the class to refer to itself for the assignment to work. This is because (in addition to being named arbitrarily), self refers to instances and not classes. At the time that the suspect line of code attempts to run, there is as of yet no class for it to refer to. Not that it would refer to the class if there was.
In a method, you can always use type(self). That will get the subclass of MyClass that created the current instance. If you want to hard-code to MyClass, that name will be available in the global scope of the methods. This will allow you to do everything that your example would allow if it actually worked. E.g, you can just do MyClass.some_attribute inside your methods.
You probably want to modify the class attributes after class creation. This can be done with decorators or on an ad-hoc basis. Metaclasses may be a better fit. Without knowing what you actually want to do though, it's impossible to say.
UPDATE:
Here's some code to do what you want. It uses a metaclass AutoViewConfigMeta and a new decorator to mark the methods that you want view_config applied to. I spoofed the view_config decorator. It prints out the class name when it's called though to prove that it has access to it. The metaclass __new__ just loops through the class dictionary and looks for methods that were marked by the auto_view_config decorator. It cleans off the mark and applies the view_config decorator with the appropriate class name.
Here's the code.
# This just spoofs the view_config decorator.
def view_config(route=''):
def dec(f):
def wrapper(*args, **kwargs):
print "route={0}".format(route)
return f(*args, **kwargs)
return wrapper
return dec
# Apply this decorator to methods for which you want to call view_config with
# the class name. It will tag them. The metaclass will apply view_config once it
# has the class name.
def auto_view_config(f):
f.auto_view_config = True
return f
class AutoViewConfigMeta(type):
def __new__(mcls, name, bases, dict_):
#This is called during class creation. _dict is the namespace of the class and
# name is it's name. So the idea is to pull out the methods that need
# view_config applied to them and manually apply them with the class name.
# We'll recognize them because they will have the auto_view_config attribute
# set on them by the `auto_view_config` decorator. Then use type to create
# the class and return it.
for item in dict_:
if hasattr(dict_[item], 'auto_view_config'):
method = dict_[item]
del method.auto_view_config # Clean up after ourselves.
# The next line is the manual form of applying a decorator.
dict_[item] = view_config(route=name)(method)
# Call out to type to actually create the class with the modified dict.
return type.__new__(mcls, name, bases, dict_)
class simpleObject(object):
__metaclass__ = AutoViewConfigMeta
class Test(simpleObject):
#auto_view_config
def activateTheView(self):
foo = 'bar'
print foo
if __name__=='__main__':
t = Test()
t.activateTheView()
Let me know if you have any questions.
Python has an "explict is better than implicit" design philosophy.
Many languages have an implicit pointer or variable in the scope of a method that (e.g. this in C++) that refers to the object through which the method was invoked. Python does not have this. Here, all bound methods will have an extra first argument that is the object through which the method was invoked. You can call it anything you want (self is not a keyword like this in C++). The name self is convention rather than a syntactic rule.
Your method myFunction defines the variable self as a parameter so it works. There's no such variable at the class level so it's erroring out.
So much for the explanation. I'm not aware of a straightforward way for you to do what you want and I've never seen such requirement in Python. Can you detail why you want to do such a thing? Perhaps there's an assumption that you're making which can be handled in another way using Python.
self is just a name, your self in this case is a class variable and not this for the object using which it is called,
self is treated as a normal variable and it is not defined, where as the self in the function comes from the object used for calling.
you want to treat the object reference in self as a class variable which is not possible.
self isn't a keyword, it's just a convention. The methods are attributes of the class object (not the instance), but they receive the instance as their first argument. You could rename the argument to xyzzy if you wanted and it would still work the same way.
But (as should be obvious) you can't refer to a method argument outside the body of the method. Inside a class block but outside of any method, self is undefined. And the concept wouldn't even make sense -- at the time the class block is being evaluated, no instance of the class can possibly exist yet.
Because the name self is explicitly defined as part of the arguments to myFunction. The first argument to a method is the instance that the method was called on; in the class body, there isn't an "instance we're dealing with", because the class body deals with every possible instance of the class (including ones that don't necessarily exist yet) - so, there isn't a particular object that could be called self.
If you want to refer to the class itself, rather than some instance of it, this is spelled self.__class__ (or, for new-style classes in Py2 and all classes in Py3, type(self)) anywhere self exists. If you want to be able to deal with this in situations where self doesn't exist, then you may want to look at class methods which aren't associated with any particular instance, and so take the class itself in place of self. If you really need to do this in the class body (and, you probably don't), you'll just have to call it by name.
You can't refer to the class itself within the class body because the class doesn't exist at the time that the class body is executed. (If the previous sentence is confusing, reading up about metaclasses will either clear this up or make you more confused.)
Within an instance method, you can refer to the class of the instance with self.__class__, but be careful here. This will be the instance's actual class, which through the power of inheritance might not be the class in which the method was defined.
Within a class method, the class is passed in as the first argument, much like instances are the first argument to instance methods:
class MyClass(object):
#classmethod
def foo(cls):
print cls.__name__
MyClass.foo() # Should print "MyClass"
As with instance methods, the actual class might differ due to inheritance.
class OtherClass(MyClass):
pass
OtherClass.foo() # Should print "OtherClass"
If you really need to refer to MyClass within a method of MyClass, you're pretty much going to have to refer to it as MyClass unless you use magic. This sort of magic is more trouble than it is worth.
This question already has answers here:
Difference between #staticmethod and #classmethod
(35 answers)
Why do we use #staticmethod?
(4 answers)
Closed last month.
I ran into unbound method error in python with this code:
import random
class Sample(object):
def drawSample(samplesize, List):
sample = random.sample(List, samplesize)
return sample
Choices=range(100)
print(Sample.drawSample(5, Choices))
I was able to fix the problem by adding #staticmethod to the method. However, I don't really understand the situation.
What is the point of using "static" methods? Why does it solve the problem in this code, and why are they ever necessary? Conversely, why would I ever not want to do it (i.e., why is extra code needed to make the method static)?
See this article for detailed explanation.
TL;DR
1.It eliminates the use of self argument.
2.It reduces memory usage because Python doesn't have to instantiate a bound-method for each object instiantiated:
>>>RandomClass().regular_method is RandomClass().regular_method
False
>>>RandomClass().static_method is RandomClass().static_method
True
>>>RandomClass.static_method is RandomClass().static_method
True
3.It improves code readability, signifying that the method does not depend on state of the object itself.
4.It allows for method overriding in that if the method were defined at the module-level (i.e. outside the class) a subclass would not be able to override that method.
Static methods have limited use, because they don't have access to the attributes of an instance of a class (like a regular method does), and they don't have access to the attributes of the class itself (like a class method does).
So they aren't useful for day-to-day methods.
However, they can be useful to group some utility function together with a class - e.g. a simple conversion from one type to another - that doesn't need access to any information apart from the parameters provided (and perhaps some attributes global to the module.)
They could be put outside the class, but grouping them inside the class may make sense where they are only applicable there.
You can also reference the method via an instance or the class, rather than the module name, which may help the reader understand to what instance the method is related.
This is not quite to the point of your actual question, but since you've said you are a python newbie perhaps it will be helpful, and no one else has quite come out and said it explicitly.
I would never have fixed the above code by making the method a static method. I would either have ditched the class and just written a function:
def drawSample(samplesize,List):
sample=random.sample(List,samplesize)
return sample
Choices=range(100)
print drawSample(5,Choices)
If you have many related functions, you can group them in a module - i.e, put them all in the same file, named sample.py for example; then
import sample
Choices=range(100)
print sample.drawSample(5,Choices)
Or I would have added an __init__ method to the class and created an instance that had useful methods:
class Sample(object):
'''This class defines various methods related to the sample'''
def __init__(self, thelist):
self.list = thelist
def draw_sample(self, samplesize):
sample=random.sample(self.list,samplesize)
return sample
choices=Sample(range(100))
print choices.draw_sample(5)
(I also changed the case conventions in the above example to match the style recommended by PEP 8.)
One of the advantages of Python is that it doesn't force you to use classes for everything. You can use them only when there is data or state that should be associated with the methods, which is what classes are for. Otherwise you can use functions, which is what functions are for.
Why one would want to define static methods?
Suppose we have a class called Math then
nobody will want to create object of class Math
and then invoke methods like ceil and floor and fabs on it.
So we make them static.
For example doing
>> Math.floor(3.14)
is much better than
>> mymath = Math()
>> mymath.floor(3.14)
So they are useful in some way. You need not create an instance of a class to use them.
Why are not all methods defined as static methods?
They don't have access to instance variables.
class Foo(object):
def __init__(self):
self.bar = 'bar'
def too(self):
print self.bar
#staticmethod
def foo():
print self.bar
Foo().too() # works
Foo.foo() # doesn't work
That is why we don't make all the methods static.
The alternatives to a staticmethod are: classmethod, instancemethod, and function. If you don't know what these are, scroll down to the last section. If a staticmethod is better than any of these alternatives, depends on for what purpose it is written.
advantages of the Python static method
If you don't need access to the attributes or methods of the class or instance, a staticmethod is better than a classmethod or instancemethod. That way it is clear (from the #staticmethod decorator) that the class' and instance's state is not read or modified. However, using a function makes that distinction even clearer (see disadvantages).
The call signature of a staticmethod is the same as that of a classmethod or instancemethod, namely <instance>.<method>(<arguments>). Hence it can easily be replaced by one of the three if that is needed later on or in a derived class. You can't do that with a simple function.
A staticmethod can be used instead of a function to make clear that it subjectively belongs to a class and to prevent namespace conflicts.
disadvantages of the Python static method
It cannot access attributes or methods of the instance or class.
The call signature of a staticmethod is the same as that of a classmethod or instancemethod. This masks the fact that the staticmethod does not actually read or modify any object information. This makes code harder to read. Why not just use a function?
A staticmethod is difficult to re-use if you ever need to call it from outside the class/instance where it was defined. If there is any potential for re-use, a function is the better choice.
The staticmethod is seldom used, so people reading code that includes one may take a little longer to read it.
alternatives to a static method in Python
To address discuss the advantages of the staticmethod, we need to know what the alternatives are and how they differ from each other.
The staticmethod belongs to a class but cannot access or modify any instance or class information.
There are three alternatives to it:
The classmethod has access to the caller's class.
The instancemethod has access to the caller's instance and its class.
The function has nothing to do with classes. It is the closest in capability to the staticmethod.
Here's what this looks like in code:
# function
# has nothing to do with a class
def make_cat_noise(asker_name):
print('Hi %s, mieets mieets!' % asker_name)
# Yey, we can make cat noises before we've even defined what a cat is!
make_cat_noise('JOey') # just a function
class Cat:
number_of_legs = 4
# special instance method __init__
def __init__(self, name):
self.name = name
# instancemethod
# the instance (e.g. Cat('Kitty')) is passed as the first method argument
def tell_me_about_this_animal(self, asker_name):
print('Hi %s, This cat has %d legs and is called %s'
% (asker_name, self.number_of_legs, self.name))
# classmethod
# the class (e.g. Cat) is passed as the first method argument
# by convention we call that argument cls
#classmethod
def tell_me_about_cats(cls, asker_name):
print("Hi %s, cats have %d legs."
% (asker_name, cls.number_of_legs))
# cls.name # AttributeError because only the instance has .name
# self.name # NameError because self isn't defined in this namespace
# staticmethod
# no information about the class or the instance is passed to the method
#staticmethod
def make_noise(asker_name):
print('Hi %s, meooow!' % asker_name)
# class and instance are not accessible from here
# one more time for fun!
make_cat_noise('JOey') # just a function
# We just need the class to call a classmethod or staticmethod:
Cat.make_noise('JOey') # staticmethod
Cat.tell_me_about_cats('JOey') # classmethod
# Cat.tell_me_about_this_animal('JOey') # instancemethod -> TypeError
# With an instance we can use instancemethod, classmethod or staticmethod
mycat = Cat('Kitty') # mycat is an instance of the class Cat
mycat.make_noise('JOey') # staticmethod
mycat.tell_me_about_cats('JOey') # classmethod
mycat.tell_me_about_this_animal('JOey') # instancemethod
When you call a function object from an object instance, it becomes a 'bound method' and gets the instance object itself is passed in as a first argument.
When you call a classmethod object (which wraps a function object) on an object instance, the class of the instance object gets passed in as a first argument.
When you call a staticmethod object (which wraps a function object), no implicit first argument is used.
class Foo(object):
def bar(*args):
print args
#classmethod
def baaz(*args):
print args
#staticmethod
def quux(*args):
print args
>>> foo = Foo()
>>> Foo.bar(1,2,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got int instance instead)
>>> Foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> Foo.quux(1,2,3)
(1, 2, 3)
>>> foo.bar(1,2,3)
(<Foo object at 0x1004a4510>, 1, 2, 3)
>>> foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> foo.quux(1,2,3)
(1, 2, 3)
static methods are great because you don't have to declare an instance of the object to which the method belongs.
python's site has some great documentation on static methods here:
http://docs.python.org/library/functions.html#staticmethod
In my estimation, there is no single performance benefit of using #staticmethods compared to just defining the function outside of and separate from the class it would otherwise be a #staticmethod of.
The only thing I would say justifies their existence is convenience. Static methods are common in other popular programming languages, so why not python? If you want to create a function with behavior that is very closely associated with the class you are creating it for but it doesn't actually access/modify the internal data of an instance of the class in a way that justifies conceptualizing it as a typical method of that class then slap a #staticmethod above it and anyone reading your code will immediately learn a lot about the nature of the method and its relationship to the class.
One thing I occasionally like to do is place functionality that my class uses internally a lot into private #staticmethods. That way I do not clutter the API exposed by my module with methods that no one using my module would ever need to see let alone use.
Static methods have almost no reason-to-be in Python. You use either instance methods or class methods.
def method(self, args):
self.member = something
#classmethod
def method(cls, args):
cls.member = something
#staticmethod
def method(args):
MyClass.member = something
# The above isn't really working
# if you have a subclass
Because namespacing functions is nice (as was previously pointed out):
When I want to be explicit about methods that don't change the state of the object, I use static methods. This discourages people on my team to start changing the object's attributes in those methods.
When i refactor really rotten code, I start by trying to make as many methods #staticmethod as possible. This allows me then to extract these methods into a class - though I agree, this is rarely something I use, it did came in helpful a few times.