On Fri, Mar 6, 2009 at 7:10 PM, Senthil Kumaran <orsent...@gmail.com> wrote: > On Thu, Mar 5, 2009 at 6:29 PM, VIJAY KUMAR <vnbang2...@yahoo.com> wrote: >> Can some one please explain me with example about >> 1) classmethod >> 2) staticmethod >> 3) Decorators >
I will try to explain this the other way around, i.e starting with functions and thinking of adding them to classes. I guess that offers a different perspective to understanding static & class methods, decorators too. It also tells you that there is nothing "special" about methods in Python classes, they are just functions with some implicit arguments. Let us say you are the guy who truly believes in dynamic creation of classes. You want to attach methods as you go along. For this purpose, you define the simplest of classes. >>> class C:pass ... You want to populate this class with 3 methods, one for adding, second for subtracting and third for multiplying two numbers. While you do this, you also want to explore the different possibilities of doing this. First you define your "add" function. >>> def add(a,b): return a + b ... Pretty simple, right ? Now you are naive w.r.t Python and its classes, and someone told you that in Python you can attach dynamic attributes to almost anything, so you do this, which is very natural indeed. >>> C.add = add No problems there. Now you try to call it on the class C with 2 arguments. >>> C.add(10,10) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method add() must be called with C instance as first argument (got int instance instead) Well, this is unexpected right ? The answer is yes, if you are unfamiliar with Python instance methods, not otherwise. The issue if you call a function on a Python class/instance, it should be either a class/instance method respectively unless qualified otherwise. And in Python ,instance methods are called with an implicit "self" first argument, which must be explicitly done by the programmer when he defines the method. However, you are adamant you don't want to change your function and still call it on the class. How can this be done ? This is where "staticmethod" helps you. It is somewhat similar to a C++ static function in that there is only a single instance and it is not bound to the class or its instance. It is just "is", so this is best option for adding a function to a class. This is how you do it in Python. >>> C.add = staticmethod(add) Now, >>> C.add(10,10) 20 Voila! Now you are wiser about the secret machinations of Python classes, so you wise up when you add the next function to the class as a method. Here is your "subtract" method. >>> def sub(self, a,b): print self;return a - b ... Why the first "self" ? Because you are planning to add this as an instance method to class "C"' and you have realized the hard way that Python implicitly passes the instance to such methods. Since this is an instance method, no cast is necessary. >>> C.sub = sub Now you create an instance of C and call "sub" on it. >>> c=C() >>> c.sub(20,10) <__main__.C instance at 0x7ff1fcd1ef38> 10 All well, and that is good! You are wise now, but not fully wise like the Python sage, so you think, "Hey, why not try calling this on the class instead of the instance ? Since I have added an explicit self, maybe it will work ?" So you do this, >>> C.sub(20, 10) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method sub() must be called with C instance as first argument (got int instance instead) Chaos results... This is because, since you are calling "sub" on the class, not the instance and it is not qualified as anything else, Python does not pass any instance implicit argument to the method, instead calls it like a static method. However the method expects the implicit instance argument as first argument and hence the error. How to resolve the problem while still keeping the function definition the same ? Answer: Make the function a classmethod. Class methods are somewhere between static and instance methods. They are similar to static methods in that you can call them on the class as well as on the instance, but similar to instance methods in that like an instance method, Python passes the class object implicitly to them, instead of the instance object. So you wise up and do so for your next "mul" method. >>> def mul(cls, a,b): print cls;return a * b ... And you add it to your class as a "classmethod" like this, >>> C.mul = classmethod(mul) >>> C.mul(10,20) __main__.C 200 However this can be called on the instance also. In this case, Python makes sure it passes the instance's class as the first argument. >>> c.mul(10,20) __main__.C 200 As you can see, I added the "print" statements to see what is getting printed. In "sub" it is the instance and in "mul" it is the class. I am summarizing the 3 musketeers here. 1. Instance method - Associated to a class's instance. The instance object is passed as implicit first argument, which is often denoted by "self". Can be called only on class instances. 2. Class method - Associated to the class. The class object is passed as implicit first argument, which is often denoted by "cls". Normally called on class objects, but can be called on instances also in which case the instance is automagically "downed" to the class. 3. Static method - Associated to none. The static method is like a function living its life attaching itself to the class's name space, but it has no loyalty towards either the class or its instances. It can be called on the class or its instances. No implicit first argument is passed. This is the way to attach stand-alone functions to a class. Hope this is now ultra clear.. If you still are not clear, ping me and I will let you know by 50K course details ;) -Anand _______________________________________________ BangPypers mailing list BangPypers@python.org http://mail.python.org/mailman/listinfo/bangpypers