The best way to invoke methods in Python class declarations?
Say I am declaring a class C and a few of the declarations are very similar. I'd like to use a function f to reduce code repetition for these declarations. It's possible to just declare and use f as usual:
>>> class C(object): ... def f(num): ... return '<' + str(num) + '>' ... v = f(9) ... w = f(42) ... >>> C.v '<9>' >>> C.w '<42>' >>> C.f(4) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method f() must be called with C instance as first argument (got int instance instead)
Oops! I've inadvertently exposed f to the outside world, but it doesn't take a self argument (and can't for obvious reasons). One possibility would be to del the function after I use it:
>>> class C(object): ... def f(num): ... return '<' + str(num) + '>' ... v = f(9) ... del f ... >>> C.v '<9>' >>> C.f Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: type object 'C' has no attribute 'f'
But what if I want to use f again later, after the declaration? It won't do to delete the function. I could make it "private" (i.e., prefix its name with __) and give it the @staticmethod treatment, but invoking staticmethod objects through abnormal channels gets very funky:
>>> class C(object): ... @staticmethod ... def __f(num): ... return '<' + str(num) + '>' ... v = __f.__get__(1)(9) # argument to __get__ is ignored... ... >>> C.v '<9>'
I have to use the above craziness because staticmethod objects, which are descriptors, are not themselves callable. I need to recover the function wrapped by the staticmethod object before I can call it.
There has got to be a better way to do this. How can I cleanly declare a function in a class, use it during its declaration, and also use it later from within the class? Should I even be doing this?
Quite simply, the solution is that f does not need to be a member of the class. I am assuming that your thought-process has gone through a Javaish language filter causing the mental block. It goes a little something like this:
def f(n): return '<' + str(num) + '>' class C(object): v = f(9) w = f(42)
Then when you want to use f again, just use it
>>> f(4) '<4>'
I think the moral of the tale is "In Python, you don't have to force everything into a class".