TNM
TNM

Reputation: 1421

Pass argument to an instance of a class to implicitely call a method

I recently saw something like this in a python library (PyTorch):

class A(BaseClass):
      def __init__(self,b,c):
           self.b =b 
           self.c = c
      def forward(self,d,e):
         return self.b + self.c + d + e

a_instance = A(1,2)
assert a_instance(d=4,e=5) == a_instance.forward(4,5) 

where instead of directly calling the method "forward" inside the Class A, you can just pass the arguments to an instance of the class and under the hood it passes them to the "forward" function and calls it.

I very much like to know how to implement something like this. Any explanation to shed a light on this is very much appreciated.

PS: This is my made up example not the real thing.

Upvotes: 0

Views: 125

Answers (2)

ljetibo
ljetibo

Reputation: 3094

This depends on how BaseClass is defined. For example in a regular situation you would have something as follows:

>>> class B(object):
    def __init__(self):
        pass
>>> B("sa")

Traceback (most recent call last):
  File "<pyshell#85>", line 1, in <module>
    B("sa")
TypeError: __init__() takes exactly 1 argument (2 given)

If someone defined BaseClass as a metaclass though you would have a situation similar to this: ```

>>> class CallableClass(type):
    def __new__(self, a):
        print "Look at me, making life harder for everyone: "+str(a)


>>> class B(CallableClass):
    def __init__(self):
        pass


>>> B("Do I really need to?")
Look at me, making life harder for everyone: Do I really need to?

```

To get what you want you would do something like

>>> class CallableClass(type):
    def __new__(self, a):
        print "Look at me, making life harder for everyone: "+str(a)
        self.a = a
        return self


>>> class B(CallableClass):
    def __init__(self):
        pass


>>> a = B("Do I really need to?")
Look at me, making life harder for everyone: Do I really need to?
>>> a.a
'Do I really need to?'

but as my example exemplifies: why? 9/10 times you don't really need metaclasses and you really really, really, don't want them mixed up with your work - it's hard to debug, it's hard to write, it's hard to think about. Maybe this is an xyz question?


EDIT:

>>> class IsCallable(object):
    def __init__(self):
        print("this is init")
    def __call__(self):
        print("this is call")

>>> class C(IsCallable):
    def __init__(self):
        IsCallable.__init__(self)
        pass
>>> C()
this is init
<__main__.C object at 0x7f32b98ebdd0>
>>> C()()
this is init
this is call

Upvotes: 1

Abhijith Asokan
Abhijith Asokan

Reputation: 1875

You can use __call__ method.

class A():
    def __init__(self,b,c):
        self.b =b 
        self.c = c
    def forward(self,d,e):
        return self.b + self.c + d + e

    def __call__(self,d,e):
        return self.forward(d,e)
a_instance = A(1,2)
assert a_instance(d=4,e=5) == a_instance.forward(4,5) 

Upvotes: 3

Related Questions