views:

70

answers:

4

Being probably one of the worst OOP programmers on the planet, I've been reading through a lot of example code to help 'get' what a class can be used for. Recently I found this example:

class NextClass:                            # define class
    def printer(self, text):                # define method
        self.message = text                 # change instance
        print self.message                  # access instance

x = NextClass()                             # make instance

x.printer('instance call')              # call its method

print x.message                               # instance changed

NextClass.printer(x, 'class call')      # direct class call

print x.message                               # instance changed again

It doesn't appear there is any difference between what the direct class call does and the instance call does; but it goes against the Zen to include features like that without some use to them. So if there is a difference, what is it? Performance? Overhead reduction? Maybe readability?

+1  A: 

In this situation, there is no difference. In both calls, you are supplying an instance of that class:

x.printer('instance call')  # you supplied x and then called its printer method
NextClass.printer(x, 'class call')  # you supplied x as a parameter this time

Normally, though, I wouldn't write the second method very often. I usually think of any method that operates on an instance as an instance method. Things like:

car.drive('place')
car.refuel
car.impound

And, I use class methods to operate more generally (I'm struggling to describe this):

Car.numberintheworld # returns the number of cars in the world (or your program)

Here's some more help, for your reading.

Jon Smock
A: 

You use class methods to add functionality, that is not instance dependant, which means, that it doesn't use any data stored in the instance. Look for example at the datetime from datetime module. You can instantize it and have an object representing some point in time. Or you can call certain methods directly on the class like now, which will give you object representing time at the point of calling the method.

gruszczy
A: 

This might give you a better clarification.

When an instance attribute is referenced that isn’t a data attribute, its class is searched. If the name denotes a valid class attribute that is a function object, a method object is created by packing (pointers to) the instance object and the function object just found together in an abstract object (i.e. this method object). When the method object is called with an argument list, a new argument list is constructed from the instance object and the argument list, and the function object is called with this new argument list.

simplyharsh
+2  A: 

There is no difference. instance.method(...) is class.method(instance, ...). But this doesn't go against the Zen, since it says (emphasis mine):

There should be one-- and preferably only one --obvious way to do it.

The second way is possible, and everyone with good knowledge of Python should know that (and why), but it's a nonobvious way of doing that, nobody does it in real code.

So why is it that way? It's just how methods work in any language - a method is some code that operates on an object/instance (and possibly more arguments). Except that usually, the instance is supplied implicitly (e.g. this in C++/Java/D) - but since the Zen says "explicit is better than implicit", self is explicitly a parameter of every method, which inevitable allows this. Explicitly prohibiting it would be pointless.

And apart from that, the fact that methods are not forced to (implicitly) take an instance allows class methods and static methods to be defined without special treatment of the language - the first is just a method that expects a class instead of an instance, and the latter is just a method that doesn't expect an instance at all.

delnan
Incredible explanation delnan, you always seem to be able to clear this stuff up for me!
yrsnkd
(A == comparison asserts your corectness, also.)
yrsnkd