Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overload a method with a function at runtime

OK, I'll admit upfront this is a mega kludge and that I could definately implement this better. It's only morbid curiosity that's driving me to find out how I could do this.

class SomeClass(object):
    def __init__(self):
        def __(self, arg):
            self.doStuff(arg)
        self.overLoaded = __
    def doStuff(self, string):
        print string

SomeClass().overLoaded("test string")

This returns a parameter error because I'm only supplying overLoaded() with one argument instead of two. Is there some magic to tell the interpreter that it's now a method of a class (I tried decorating it with @classmethod, I always understood this to be it's purpose??)

like image 463
richo Avatar asked Dec 23 '22 07:12

richo


1 Answers

Don't worry about the self parameter, the function already has that from local scope.

class SomeClass(object):
    def __init__(self):
        def __(arg):
            self.bar(arg)
        self.foo = __
    def foo(self, arg):
        print "foo", arg
    def bar(self, arg):
        print "bar", arg

SomeClass().foo("thing") # prints "bar thing"

When creating an instance (after __new__, iirc, but before __init__) Python binds all the methods to automagically supply the instance as the first argument. If you're adding a method later then you need to supply the instance manually. As you are defining the function with self already in scope you don't need to pass it again.

Python's new module is not a solution as it has been deprecated since 2.6. If you want to create a "real" instance method do it with the partial decorator like this:

import functools

class SomeClass(object):
    def __init__(self):
        def __(self, arg):
            self.bar(arg)
        self.foo = functools.partial(__, self)
    def foo(self, arg):
        print "foo", arg
    def bar(self, arg):
        print "bar", arg

SomeClass().foo("thing") # prints "bar thing"
like image 78
sj26 Avatar answered Jan 06 '23 14:01

sj26