with your host, Amar
Python has the notion of class methods. I haven't quite wrapped my head around this concept.
In Python, everything's a namespace. Classes are namespaces whose functions all have an implicit first parameter, 'self.' 'self' represents an anonymous namespace, i.e. an object. (Objects are namespaces too!) A new anonymous namespace is created when an object is constructed, and it's passed as a hidden first argument whenever the object's methods are called.
class Foo: # defines namespace Foo
def set_name(self, name): # defines instance method set_name(name), implicit first argument
self.name = name # have to use 'self' when changing object state
myFoo = Foo() # creates new anonymous namespace, #234121 or whatever
myFoo.set_name("Mary") # calls Foo.set_name(#234121, "Mary")
myFoo.get_name() # returns #234121.name
That covers instance methods. But Python developers also wanted something equivalent to static class methods in C++. So they introduced the notion of "decorators." Decorators are little directives that tell the interpreter to add or not add implicit parameters. The syntax is similar to compiler directives in C++:
doSomething(self, arg): # instance method
doSomethingElse(arg): # decorated with static, no implicit 'self' parameter
myFoo = Foo()
myFoo.doSomething('22skidoo') # ok
myFoo.doSomething('hello', '22skidoo') # error = doSomething only takes one explicit arg
myFoo.doSomethingElse('22skidoo') # ok, static method can be invoked via instance, no implicit 'self' parameter
Foo.doSomethingElse('22skidoo') # ok, same as above but invoked via class
Aside from the whole "callable via object" thing, the @staticmethod decorator is pretty similar to the "static" declaration in C++. But Python also has @classmethod, which (though confusingly named) does not refer to instance methods of a class.
Class methods have an implicit first argument, like 'self'. But this first argument is a reference to the namespace of the class itself, not some instance of the class. You can use this reference to access everything in the class namespace.
What's the point? After all, static methods of Foo can already access everything in the Foo namespace. Why bother passing it in as a parameter? The answer (I think) is that unlike static method, class methods can mix in subclass functionality with base class functionality. e.g.
modifyAmount = 1 # static variable, Foo.modifyAmount
return var + modifyAmount # always uses Foo.modifyAmount
return var + cls.modifyAmount # accesses modifyAmount via implicit cls argument
modifyAmount = 100 # static variable, Bar.modifyAmount
myFoo = Foo()
myBar = Bar()
myFoo.modifyStatic(4) # returns 5
myBar.modifyStatic(4) # returns 5, even though Bar.modifyAmount is 100
myFoo.modifyClass(4) # returns 5, same as myFoo.modifyStatic
myBar.modifyClass(4) # returns 104, because implicit cls argument was used when getting modifyAmountThis looks like one of the classic software design patterns -- Mixin or Strategy or what have you. Basically the base class can define some functionality that requires subclasses to 'fill in' particular details. Like a base database class that knows about general cursors and querying and stuff, but lets particular table subclasses fill in the details of their specific queries/data.
In C++ you could accomplish the same thing by defining a non-virtual function that uses virtual functions... right? Is that all @classmethod accomplishes? Like I said, I haven't quite figured it out yet. Let's just say my interest is not entirely academic.
previously on Geek Korner