Should methods that do not act on object data be made static? - python

I have a class that includes some auxiliary functions that do not operate on object data. Ordinarily I would leave these methods private, but I am in Python so there is no such thing. In testing, I am finding it slightly goofy to have to instantiate an instance of my class in order to be able to call these methods. Is there a solid theoretical reason to choose to keep these methods non-static or to make them static?

If a method does not need access to the current instance, you may want to make it either a classmethod, a staticmethod or a plain function.
A classmethod will get the current class as first param. This enable it to access the class attributes including other classmethods or staticmethods. This is the right choice if your method needs to call other classmethods or staticmethods.
A staticmethod only gets it's explicit argument - actually it nothing but a function that can be resolved on the class or instance. The main points of staticmethods are specialization - you can override a staticmethod in a child class and have a method (classmethod or instancemethod) of the base class call the overridden version of the staticmethod - and eventually ease of use - you don't need to import the function apart from the class (at this point it's bordering on lazyness but I've had a couple cases with dynamic imports etc where it happened to be handy).
A plain function is, well, just a plain function - no class-based dispatch, no inheritance, no fancy stuff. But if it's only a helper function used internally by a couple classes in the same module and not part of the classes nor module API, it's possibly just what you're looking for.
As a last note: you can have "some kind of" privacy in Python. Mostly, prefixing a name (whether an attribute / method / class or plain function) with a single leading underscore means "this is an implementation detail, it's NOT part of the API, you're not even supposed to know it exists, it might change or disappear without notice, so if you use it and your code breaks then it's your problem".

If you want to keep said methods in the class just for structural reasons, you might as well make them static, by using the #staticmethod decorator:
class Foo():
#staticmethod
def my_static_method(*args, **kwargs):
....
Your first argument will not be interpretted as the object itself, and you can use it from either the class or an object from that class. If you still need to access class attributes in your method though, you can make it a class method:
class Bar():
counter = 0
#classmethod
def my_class_method(cls, *args, **kwargs):
cls.counter += 1
...
Your first argument of the class method will obviously be the class instead of the instance.
If you do not use any class or instance attribute, I can see no "theoretical" reason to not make them static. Some IDE's even highlight this as a soft warning to prompt you to make the method static if it does not use or mutate any class/instance attribute.

Related

How are Python static methods useful (except as a namespace)? [duplicate]

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.

Why do we use #staticmethod?

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.

Why does "self" outside a function's parameters give a "not defined" error?

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.

how to override class, or undeclare class or redeclare a Class in python?

is there any possible to override class, or undeclare class or redeclare a Class in python?
Yes, just declare it again:
class Foo(object): x = 1
class Foo(object): x = 2
The above code will not raise any error, and the name Foo will refer to the second class declared. Note however, that the class declared by the first declaration will still exist if anything refers to it, e.g. an instance, or a derived class.
This means that existing instances will not change class when you declare a new class with the same name, and existing subclasses will not magically inherit from the new class.
Probably the simplest method to deal with subclasses is to also re-declare them, so they inherit from the "renewed" base class. An alternative would be to mess with their __bases__ property, although I can't tell you if that would have unexpected results (there will almost certainly be some corner cases where this would not work).
As to existing instances, it is possible to re-assign their __class__ property with a new class. This does present two issues - first you have to find them (see this question: Printing all instances of a class), and second of all, items stored in instance __dict__ or __slots__ properties will still be there in those instances. If that is not something that should happen with your new class definition, you will have to write appropriate code to handle that as part of the transformation.
IN summary, it's unlikely to be worth it except in quite simple cases. If you need complete uptime for a running system, you might be better using a replication-based approach to achieve code changes.
Update: If this is the kind of thing you know you're going to do, another solution would be to use the strategy pattern.
Undeclare a class using del className as usual.

What is the purpose of static methods? How do I know when to use one? [duplicate]

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.

Categories

Resources