tags:

views:

216

answers:

6

I ran into unbound method error in python with the code

class Sample(object):
'''This class defines various methods related to the sample'''

    def drawSample(samplesize,List):
        sample=random.sample(List,samplesize)
        return sample

Choices=range(100)
print Sample.drawSample(5,Choices)

After reading many helpful posts here, I figured how I could add @staticmethod above to get the code working. I am python newbie. Can someone please explain why one would want to define static methods? Or, why are not all methods defined as static methods.

Thanks in advance.

+1  A: 

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

David
Thanks David. But why then not define every method as a static method, since they also work on instances. Are there any drawbacks of doing so?
Curious2learn
@Curious2learn: No, with static methods you have no access to the instance: *The instance is ignored except for its class.*
Felix Kling
That argument would be true in Java, where functions can not live by itself but are always defined in the context of a class. But in Python you can have functions and static class functions. This answer doesn't really show why to choose a static method in stead of a method not in a class.
extraneon
@extraneon - that's more a matter of code organizational preferences; having static methods gives one the extra option.
Charles Duffy
@Felix - Thanks. This clarifies why every method should not be a static method.
Curious2learn
+2  A: 

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
Georg
You said "almost". Is there a place where they can be better than the alternatives?
Javier Badia
@Javier: I can't think of one, but there probably is one, why would that method be included in the Python library otherwise?
Georg
@Javier, @Georg: You have great faith that the Python corpus does not have cruft.
Charles Merriam
+2  A: 

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.

TheMachineCharmer
But why not a package math? Python has packages for that, you don't _need_ a class definition to create a namespace.
extraneon
@extraneon: Yup dude I know that but I wanted to have something simple and familiar for explanation so I used `Math`. That is why I capitalized `M`.
TheMachineCharmer
@TheMachineCharmer: The OP didn't ask what are static methods. He asked what's their advantage. You're explaining how to use them, not how are they useful. In your particular example, a namespace would make much more sense.
Javier Badia
@Javier Badia- :) Somebody(a c# programmer) might want to use them in this way. Also look at http://stackoverflow.com/questions/2438473/what-is-the-advantage-of-using-static-methods-in-python/2438478#2438478
TheMachineCharmer
+1  A: 

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)
Matt Anderson
+5  A: 

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.

Oddthinking
Thanks. This clarifies why every method should not be a static method.
Curious2learn
+2  A: 

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 - ie, 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.

Vicki Laidler
Thanks for the comment. I did need a class in this case because I want to work with the sample drawn. No I did not use a static method, but wanted to learn about, since I came across the term when looking up information on the error message that I got. But your advice about collecting the functions into a module without defining a class would be helpful for other functions that I need. So thanks.
Curious2learn