Hi all,

I have a class with a variety of methods, for example:

class Foo(obj):
    def meth_a:
      ...

    def meth_b:
      ...

In reality, Foo may have 50 or more methods. And for various reasons, I cannot subclass Foo. I'm using Foo in a composition class with some added functionality. Let's call this class Bar. I want Bar to have a few new methods and attributes, but quack like it was Foo. For example, when the user calls:

Bar.meth_a()

My program returns Foo.meth_a().

class Bar(obj):
   foo=Foo()
   def meth_a:
      return self.foo.meth_a()

As such, Bar seems to have all of Foo's methods. Without being able to subclass, is it possible to promote all of these methods without doing it manually? Foo() is extremely complicated and it would be quite laborious to port everything. Can anyone think of a way to do this?

Thanks

Edited 3 Years Ago by dashing.adamhughes

The first way is to define __getattr__()

class Bar(object):
    def __getattr__(self, attr):
        return getattr(self.foo, attr)

You can add some conditions on attr to avoid unexpected calls

class Bar(object):
    def __getattr__(self, attr):
        if some_condition(attr):
            return getattr(self.foo, attr)
        else:
            raise AttributeError(attr)

Another way is to define methods by a loop, eg

class Bar(object):
    for name in "meth_a meth_b meth_c".split():
        exec "def {name}(self, *args, **kwd): return self.foo.{name}(*args, **kwd)".format(name=name)
    del name

There are other ways, you could write a function which inserts methods in class Bar, etc

Edited 3 Years Ago by Gribouillis

Hi. I had to reopen this because of some unforseen issues with this implementation.

I am using getattr(); however, I need to be able to customize behavior upon the return. For example, if a method of self.foo.meth_a() returns an integer, I'd like to do one thing, but if it returns a string I'd like to do another.

I'm having trouble actually being able to intercept the return of the method that is eventually called by getattr(). I tried this:

class Bar(object):
    def __getattr__(self, attr):
        if type(getattr(self.foo, attr)) == int:
            etc...

Unfortunately, getattr makes a reference to an instance method, it does not actually call the method. In other words, type(getattr(self.foo, attr)) is an InstanceMethod not an intor string. I don't know where in my class the foo method is actually callled so I can't intercept the return.

This question has already been answered. Start a new discussion instead.