Search code examples
pythonoopencapsulation

encapsulating class calls/modifies things in the dir of original class


I have a class A encapsulating a class B instance and additional stuff. The following is a toy example.

class B(object):
    def __init__(self):
        self.b = 2
    def square(self):
        return self.b * self.b

class A(object):
    def __init__(self, x):
        self.b = B()

a = A(1)
print(a.b.square())   

Any time an A instance wants to call a method in B, I always need to do things like 'a.b'. My hope is to get rid of '.b' for user convenience. The following codes do the job.

class B(object):
    def __init__(self):
        self.b = 2
    def square(self):
        return self.b * self.b

class A(object):
    def __init__(self, x):
        self.b = B()
    def square(self):
        return self.b.square()

a = A(1)
print(a.square())

The problem is that class B is from outside library and there are lots of and different types of things in the dir. I couldn't do it one by one manually like above. Any magical ways to handle that?


Solution

  • Any magical ways to handle that?

    It's python, of course there are! You can use __getattr__ function to proxy unknown calls to b:

    class B(object):
        def shadowed(self):
            print('B.shadowed')
    
        def unshadowed(self):
            print('B.unshadowed')
    
    
    class A(object):
        def __init__(self):
            self._b = B()
    
        def shadowed(self):
            print('A.shadowed')
    
        def __getattr__(self, name):
            return getattr(self._b, name)
    
    
    test = A()
    test.shadowed()
    test.unshadowed()
    test.unknown()
    

    Result:

    A.shadowed
    B.unshadowed
    Traceback (most recent call last):
      File "/Users/Andrew/Desktop/test.py", line 23, in <module>
        test.unknown()
      File "/Users/Andrew/Desktop/test.py", line 17, in __getattr__
        return getattr(self._b, name)
    AttributeError: 'B' object has no attribute 'unknown'
    

    __getattr__ is called when the object doesn't have attribute that's being asked for.