user5423
user5423

Reputation: 145

How to redirect method calls in python?

I understand that you can use __getattr__() to access attributes that don't exist as that class's attributes. However I wanted to do the same thing with functions.

I read that python treats attributes and methods the same, so you use the __getattr__() for methods aswell. Is this true?

class container:
    def __init__(self, data):
        self.data = data

    def __getattr__(self, item):
        ##Don't know the code to put here vv
        result = getattr(self.data, item)


class data:
    def printHello(self):
        print("hello")

    def printString(self, string):
        print(string)

def main():
    someData = data()
    someContainer = container(someData)
    someContainer.printString("sup")

main()

Aim: I want to be able to write container.printHello() and have it invoke container.data.printHello(). I would also want a solution that would enable to pass parameters to printString() aswell. How would I go about doing this?

NOTE: This is a simplification. In reality I have a huge number of methods that I am constantly adding and removing and changing method names as I develop my program

Upvotes: 4

Views: 3367

Answers (3)

RGoodman
RGoodman

Reputation: 191

All you need to do is return the attribute you found.

"""
Tests

>>> c = container(data())
>>> c.printHello()
hello
>>> c.printString("Hello World")
Hello World
>>> c.printGarbage('Hello World')
Traceback (most recent call last):
  File "cont.py", line 19, in __getattr__
    result = getattr(self.data, item)
AttributeError: 'data' object has no attribute 'printGarbage'
"""

import functools

class container:
    def __init__(self, data):
        self.data = data

    def __getattr__(self, item):
        result = getattr(self.data, item)
        return result

class data:
    def printHello(self):
        print("hello")

    def printString(self, string):
        print(string)

Upvotes: 1

ifrag
ifrag

Reputation: 161

Maybe you forgot return your result? It's works for me:

def __getattr__(self, item): 
    return getattr(self.data, item)

Upvotes: 2

juanpa.arrivillaga
juanpa.arrivillaga

Reputation: 96172

You pretty much have it, you just need to return what you had.

class Container:
    def __init__(self, data):
        self.data = data
    def __getattr__(self, attr):
        return getattr(self.data, attr)

class Data:
    def print_hello(self):
        print("hello")

    def print_string(self, string):
        print(string)


Container(Data()).print_hello()
Container(Data()).print_string('foo')

Upvotes: 6

Related Questions