Assign external function to class variable in Python - python

I am trying to assign a function defined elsewhere to a class variable so I can later call it in one of the methods of the instance, like this:
from module import my_func
class Bar(object):
func = my_func
def run(self):
self.func() # Runs my function
The problem is that this fails because when doing self.func(), then the instance is passed as the first parameter.
I've come up with a hack but seems ugly to me, anybody has an alternative?
In [1]: class Foo(object):
...: func = lambda *args: args
...: def __init__(self):
...: print(self.func())
...:
In [2]: class Foo2(object):
...: funcs = [lambda *args: args]
...: def __init__(self):
...: print(self.funcs[0]())
...:
In [3]: f = Foo()
(<__main__.Foo object at 0x00000000044BFB70>,)
In [4]: f2 = Foo2()
()
Edit: The behavior is different with builtin functions!
In [13]: from math import pow
In [14]: def pow_(a, b):
....: return pow(a, b)
....:
In [15]: class Foo3(object):
....: func = pow_
....: def __init__(self):
....: print(self.func(2, 3))
....:
In [16]: f3 = Foo3()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-16-c27c8778655e> in <module>()
----> 1 f3 = Foo3()
<ipython-input-15-efeb6adb211c> in __init__(self)
2 func = pow_
3 def __init__(self):
----> 4 print(self.func(2, 3))
5
TypeError: pow_() takes exactly 2 arguments (3 given)
In [17]: class Foo4(object):
....: func = pow
....: def __init__(self):
....: print(self.func(2, 3))
....:
In [18]: f4 = Foo4()
8.0

Python functions are descriptor objects, and when attributes on a class accessing them an instance causes them to be bound as methods.
If you want to prevent this, use the staticmethod function to wrap the function in a different descriptor that doesn't bind to the instance:
class Bar(object):
func = staticmethod(my_func)
def run(self):
self.func()
Alternatively, access the unbound function via the __func__ attribute on the method:
def run(self):
self.func.__func__()
or go directly to the class __dict__ attribute to bypass the descriptor protocol altogether:
def run(self):
Bar.__dict__['func']()
As for math.pow, that's not a Python function, in that it is written in C code. Most built-in functions are written in C, and most are not descriptors.

Related

Aliase a class function to be assigned from init method

Given I have a class such as:
class Model(object):
def __init__(self, foo = 'bar'):
if foo == 'bar':
self.f = self._sse
else:
self.f = None
def _sse():
pass
Is there a way I can create an alias so I do not have to check what's the value of the non-positional argument foo? Something like
class Model(object):
alias = {'bar': _sse}
def __init__(self, foo = 'bar'):
self.f = foo
def _sse():
pass
Technical answer: you can do it by defining the target function before the initializer, referencing this function as the default argument (Python functions are objects too), and manually invoking the descriptor protocol on the target function:
>>> class Model(object):
... def _sse(self):
... print("in self._sse")
... def __init__(self, foo=_sse):
... self.f = foo.__get__(self, type(self))
...
>>> m = Model()
>>> m.f()
in self._sse
Just note that with this solution, if you want to pass another function, this function has to take self as first argument :
>>> # doesn't work
... def bar(): print("bar")
...
>>> m2 = Model(bar)
>>> m2.f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() takes no arguments (1 given)
>>> # works:
... def baaz(self): print("baaz({})".format(self))
...
>>> m3 = Model(baaz)
>>> m3.f()
baaz(<__main__.Model object at 0x7fc3e2337090>)
Now from a readability POV this is barely an improvement IMHO...
EDIT: as Aran-Fey mentions, this doesn't exactly answer the question so for a more "literal" version (and that doesn't require special definitions ordering etc):
class Model(object):
def _sse(self):
print("in self._sse")
alias = {"bar": "_sse"}
def __init__(self, foo="bar"):
self.f = getattr(self, self.alias.get(foo, "___"), None)
But this is still not improving readability...
Using #KlausD. suggestion and including alias in the __init__ method does the trick for me.
class Model(object):
def __init__(self, foo = 'bar'):
alias = {'bar': self._sse,
'bar2': self._sse2}
self.f = alias.get(foo)
def _sse(self):
print('in sse')
def _sse2(self):
print('in sse2')
m = Model(foo='bar')
m.f() # in sse
m = Model(foo='bar2')
m.f() # in sse2

Expose object properties dynamically

In [1]: class Foo():
...: pass
...:
In [2]: class Qux():
...: def __init__(self):
...: item = Foo()
...:
In [3]: a = Foo()
In [4]: setattr(a, 'superpower', 'strength')
In [5]: a.superpower
Out[5]: 'strength'
In [6]: b = Qux()
In [7]: b.item = a
In [8]: b.superpower
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-cf0e287006f1> in <module>()
----> 1 b.superpower
AttributeError: Qux instance has no attribute 'superpower'
What I would like is to define some way of calling any attribute on Qux and have it return getattr(Qux.item, <attributename>). In other words, to have b.superpower work without explicitly defining:
#property
def superpower(self):
return getattr(self.item, 'superpower')
I don't want to lose access to any properties defined on Qux itself as well, but rather to expose properties defined on Foo if they are not also on Qux.
Define a __getattr__:
class Qux(Foo):
def __init__(self):
self.item = Foo()
def __getattr__(self, attr):
return getattr(self.item, attr)
__getattr__ gets called whenever someone tries to look up an attribute of the object, but fails through normal means.
It has an evil twin called __getattribute__, which always gets called and must be used with extreme caution.
You do that by defining __getattr__, not with a property. For any attribute that cannot be found with the standard protocol, Python will call the __getattr__ method of a class.
Moreover, to store the item, you have to assign it to self.item, otherwise it is thrown at the end of Qux.__init__.
Finally, inheriting from Foo seems unecessary in that case.
class Foo:
def __init__(self, superpower):
self.superpower = superpower
class Qux:
def __init__(self, foo_item):
self.item = foo_item
def __getattr__(self, name):
return getattr(self.item, name)
Example
f = Foo('strenght')
q = Qux(f)
print(q.superpower) # 'strenght'
Inheritance
Although, it seems you half-tried to implement this with inheritance. If your intent was to extend Qux behaviour with Foo, then inheritance would be the way to go.
class Foo:
def __init__(self, superpower):
self.superpower = superpower
class Qux(Foo):
def __getattr__(self, name):
return getattr(self.item, name)
Example
q = Qux('strenght')
print(q.superpower) # 'strenght'

How to define enum values that are functions?

I have a situation where I need to enforce and give the user the option of one of a number of select functions, to be passed in as an argument to another function:
I really want to achieve something like the following:
from enum import Enum
#Trivial Function 1
def functionA():
pass
#Trivial Function 2
def functionB():
pass
#This is not allowed (as far as i can tell the values should be integers)
#But pseudocode for what I am after
class AvailableFunctions(Enum):
OptionA = functionA
OptionB = functionB
So the following can be executed:
def myUserFunction(theFunction = AvailableFunctions.OptionA):
#Type Check
assert isinstance(theFunction,AvailableFunctions)
#Execute the actual function held as value in the enum or equivalent
return theFunction.value()
Your assumption is wrong. Values can be arbitrary, they are not limited to integers. From the documentation:
The examples above use integers for enumeration values. Using integers
is short and handy (and provided by default by the Functional API),
but not strictly enforced. In the vast majority of use-cases, one
doesn’t care what the actual value of an enumeration is. But if the
value is important, enumerations can have arbitrary values.
However the issue with functions is that they are considered to be method definitions instead of attributes!
In [1]: from enum import Enum
In [2]: def f(self, *args):
...: pass
...:
In [3]: class MyEnum(Enum):
...: a = f
...: def b(self, *args):
...: print(self, args)
...:
In [4]: list(MyEnum) # it has no values
Out[4]: []
In [5]: MyEnum.a
Out[5]: <function __main__.f>
In [6]: MyEnum.b
Out[6]: <function __main__.MyEnum.b>
You can work around this by using a wrapper class or just functools.partial or (only in Python2) staticmethod:
from functools import partial
class MyEnum(Enum):
OptionA = partial(functionA)
OptionB = staticmethod(functionB)
Sample run:
In [7]: from functools import partial
In [8]: class MyEnum2(Enum):
...: a = partial(f)
...: def b(self, *args):
...: print(self, args)
...:
In [9]: list(MyEnum2)
Out[9]: [<MyEnum2.a: functools.partial(<function f at 0x7f4130f9aae8>)>]
In [10]: MyEnum2.a
Out[10]: <MyEnum2.a: functools.partial(<function f at 0x7f4130f9aae8>)>
Or using a wrapper class:
In [13]: class Wrapper:
...: def __init__(self, f):
...: self.f = f
...: def __call__(self, *args, **kwargs):
...: return self.f(*args, **kwargs)
...:
In [14]: class MyEnum3(Enum):
...: a = Wrapper(f)
...:
In [15]: list(MyEnum3)
Out[15]: [<MyEnum3.a: <__main__.Wrapper object at 0x7f413075b358>>]
Also note that if you want you can define the __call__ method in your enumeration class to make the values callable:
In [1]: from enum import Enum
In [2]: def f(*args):
...: print(args)
...:
In [3]: class MyEnum(Enum):
...: a = partial(f)
...: def __call__(self, *args):
...: self.value(*args)
...:
In [5]: MyEnum.a(1,2,3) # no need for MyEnum.a.value(1,2,3)
(1, 2, 3)
Since Python 3.11 there is much more concise and understandable way. member and nonmember functions were added to enum among other improvements, so you can now do the following:
from enum import Enum, member
def fn(x):
print(x)
class MyEnum(Enum):
meth = fn
mem = member(fn)
#classmethod
def this_is_a_method(cls):
print('No, still not a member')
def this_is_just_function():
print('No, not a member')
#member
def this_is_a_member(x):
print('Now a member!', x)
And now
>>> list(MyEnum)
[<MyEnum.mem: <function fn at ...>>, <MyEnum.this_is_a_member: <function MyEnum.this_is_a_member at ...>>]
>>> MyEnum.meth(1)
1
>>> MyEnum.mem(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'MyEnum' object is not callable
>>> MyEnum.mem.value(1)
1
>>> MyEnum.this_is_a_method()
No, still not a member
>>> MyEnum.this_is_just_function()
No, not a member
>>> MyEnum.this_is_a_member()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'MyEnum' object is not callable
>>> MyEnum.this_is_a_member.value(1)
Now a member! 1
Another less clunky solution is to put the functions in a tuple. As Bakuriu mentioned, you may want to make the enum callable.
from enum import Enum
def functionA():
pass
def functionB():
pass
class AvailableFunctions(Enum):
OptionA = (functionA,)
OptionB = (functionB,)
def __call__(self, *args, **kwargs):
self.value[0](*args, **kwargs)
Now you can use it like this:
AvailableFunctions.OptionA() # calls functionA
In addition to the answer of Bakuriu... If you use the wrapper approach like above you loose information about the original function like __name__, __repr__
and so on after wrapping it. This will cause problems for example if you want to use sphinx for generation of source code documentation. Therefore add the following to your wrapper class.
class wrapper:
def __init__(self, function):
self.function = function
functools.update_wrapper(self, function)
def __call__(self,*args, **kwargs):
return self.function(*args, **kwargs)
def __repr__(self):
return self.function.__repr__()
Building on top of #bakuriu's approach, I just want to highlight that we can also use dictionaries of multiple functions as values and have a broader polymorphism, similar to enums in Java. Here is a fictitious example to show what I mean:
from enum import Enum, unique
#unique
class MyEnum(Enum):
test = {'execute': lambda o: o.test()}
prod = {'execute': lambda o: o.prod()}
def __getattr__(self, name):
if name in self.__dict__:
return self.__dict__[name]
elif not name.startswith("_"):
value = self.__dict__['_value_']
return value[name]
raise AttributeError(name)
class Executor:
def __init__(self, mode: MyEnum):
self.mode = mode
def test(self):
print('test run')
def prod(self):
print('prod run')
def execute(self):
self.mode.execute(self)
Executor(MyEnum.test).execute()
Executor(MyEnum.prod).execute()
Obviously, the dictionary approach provides no additional benefit when there is only a single function, so use this approach when there are multiple functions. Ensure that the keys are uniform across all values as otherwise, the usage won't be polymorphic.
The __getattr__ method is optional, it is only there for syntactic sugar (i.e., without it, mode.execute() would become mode.value['execute']().
Since dictionaries can't be made readonly, using namedtuple would be better and require only minor changes to the above.
from enum import Enum, unique
from collections import namedtuple
EnumType = namedtuple("EnumType", "execute")
#unique
class MyEnum(Enum):
test = EnumType(lambda o: o.test())
prod = EnumType(lambda o: o.prod())
def __getattr__(self, name):
if name in self.__dict__:
return self.__dict__[name]
elif not name.startswith("_"):
value = self.__dict__['_value_']
return getattr(value, name)
raise AttributeError(name)

Class Inheritance in Python

I'm new to python and trying to get a list of the classes an object's class inherits from. I'm trying to do this using the bases attribute but I'm not having any success. Can someone please help me out?
def foo(C):
print(list(C.__bases__))
class Thing(object):
def f(self):
print("Yo")
class Shape(Thing):
def l(self):
print("ain't no thang")
class Circle(Shape):
def n(self):
print("ain't no shape")
test = Circle()
foo(test)
Only classes have __bases__; class instances do not. You can get the class object through an instance's __class__: use foo(test.__class__) or foo(Circle).
Use inspect, from documentation
Return a tuple of class cls’s base classes, including cls, in method
resolution order. No class appears more than once in this tuple. Note
that the method resolution order depends on cls’s type. Unless a very
peculiar user-defined metatype is in use, cls will be the first
element of the tuple.
>>> import inspect
>>> inspect.getmro(test.__class__)
(<class '__main__.Circle'>, <class '__main__.Shape'>, <class '__main__.Thing'>, <type 'object'>)
>>>
This traverses up the inheritance hierarchy & prints all classes, including object. Pretty Cool eh ?
print '\n'.join(base.__name__ for base in test.__class__.__bases__)
Or, using the inspect module:
from inspect import getmro
print '\n'.join(base.__name__ for base in getmro(test))
Your implementation of foo works. But you need to pass a class to foo, not an instance.
In [1]: def foo(C):
...: print(list(C.__bases__))
...:
In [2]: class Thing(object):
...: def f(self):
...: print("Yo")
...:
In [3]: class Shape(Thing):
...: def l(self):
...: print("ain't no thang")
...:
In [4]: class Circle(Shape):
...: def n(self):
...: print("ain't no shape")
...:
In [5]: test = Circle()
In [6]: foo(test)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-6-7b85deb1beaa> in <module>()
----> 1 foo(test)
<ipython-input-1-acd1789d43a9> in foo(C)
1 def foo(C):
----> 2 print(list(C.__bases__))
3
AttributeError: 'Circle' object has no attribute '__bases__'
In [7]: foo(Thing)
[<type 'object'>]
In [8]: foo(Circle)
[<class '__main__.Shape'>]
In [9]: foo(Shape)
[<class '__main__.Thing'>]

What is the difference between __init__ and __call__?

I want to know the difference between __init__ and __call__ methods.
For example:
class test:
def __init__(self):
self.a = 10
def __call__(self):
b = 20
The first is used to initialise newly created object, and receives arguments used to do that:
class Foo:
def __init__(self, a, b, c):
# ...
x = Foo(1, 2, 3) # __init__
The second implements function call operator.
class Foo:
def __call__(self, a, b, c):
# ...
x = Foo()
x(1, 2, 3) # __call__
Defining a custom __call__() method allows the class's instance to be called as a function, not always modifying the instance itself.
In [1]: class A:
...: def __init__(self):
...: print "init"
...:
...: def __call__(self):
...: print "call"
...:
...:
In [2]: a = A()
init
In [3]: a()
call
In Python, functions are first-class objects, this means: function references can be passed in inputs to other functions and/or methods, and executed from inside them.
Instances of Classes (aka Objects), can be treated as if they were functions: pass them to other methods/functions and call them. In order to achieve this, the __call__ class function has to be specialized.
def __call__(self, [args ...])
It takes as an input a variable number of arguments. Assuming x being an instance of the Class X, x.__call__(1, 2) is analogous to calling x(1,2) or the instance itself as a function.
In Python, __init__() is properly defined as Class Constructor (as well as __del__() is the Class Destructor). Therefore, there is a net distinction between __init__() and __call__(): the first builds an instance of Class up, the second makes such instance callable as a function would be without impacting the lifecycle of the object itself (i.e. __call__ does not impact the construction/destruction lifecycle) but it can modify its internal state (as shown below).
Example.
class Stuff(object):
def __init__(self, x, y, range):
super(Stuff, self).__init__()
self.x = x
self.y = y
self.range = range
def __call__(self, x, y):
self.x = x
self.y = y
print '__call__ with (%d,%d)' % (self.x, self.y)
def __del__(self):
del self.x
del self.y
del self.range
>>> s = Stuff(1, 2, 3)
>>> s.x
1
>>> s(7, 8)
__call__ with (7,8)
>>> s.x
7
>>> class A:
... def __init__(self):
... print "From init ... "
...
>>> a = A()
From init ...
>>> a()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: A instance has no __call__ method
>>>
>>> class B:
... def __init__(self):
... print "From init ... "
... def __call__(self):
... print "From call ... "
...
>>> b = B()
From init ...
>>> b()
From call ...
>>>
__call__ makes the instance of a class callable.
Why would it be required?
Technically __init__ is called once by __new__ when object is created, so that it can be initialized.
But there are many scenarios where you might want to redefine your object, say you are done with your object, and may find a need for a new object. With __call__ you can redefine the same object as if it were new.
This is just one case, there can be many more.
__init__ would be treated as Constructor where as __call__ methods can be called with objects any number of times. Both __init__ and __call__ functions do take default arguments.
I will try to explain this using an example, suppose you wanted to print a fixed number of terms from fibonacci series. Remember that the first 2 terms of fibonacci series are 1s. Eg: 1, 1, 2, 3, 5, 8, 13....
You want the list containing the fibonacci numbers to be initialized only once and after that it should update. Now we can use the __call__ functionality. Read #mudit verma's answer. It's like you want the object to be callable as a function but not re-initialized every time you call it.
Eg:
class Recorder:
def __init__(self):
self._weights = []
for i in range(0, 2):
self._weights.append(1)
print self._weights[-1]
print self._weights[-2]
print "no. above is from __init__"
def __call__(self, t):
self._weights = [self._weights[-1], self._weights[-1] + self._weights[-2]]
print self._weights[-1]
print "no. above is from __call__"
weight_recorder = Recorder()
for i in range(0, 10):
weight_recorder(i)
The output is:
1
1
no. above is from __init__
2
no. above is from __call__
3
no. above is from __call__
5
no. above is from __call__
8
no. above is from __call__
13
no. above is from __call__
21
no. above is from __call__
34
no. above is from __call__
55
no. above is from __call__
89
no. above is from __call__
144
no. above is from __call__
If you observe the output __init__ was called only one time that's when the class was instantiated for the first time, later on the object was being called without re-initializing.
__call__ allows to return arbitrary values, while __init__ being an constructor returns the instance of class implicitly. As other answers properly pointed out, __init__ is called just once, while it's possible to call __call__ multiple times, in case the initialized instance is assigned to intermediate variable.
>>> class Test:
... def __init__(self):
... return 'Hello'
...
>>> Test()
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: __init__() should return None, not 'str'
>>> class Test2:
... def __call__(self):
... return 'Hello'
...
>>> Test2()()
'Hello'
>>>
>>> Test2()()
'Hello'
>>>
So, __init__ is called when you are creating an instance of any class and initializing the instance variable also.
Example:
class User:
def __init__(self,first_n,last_n,age):
self.first_n = first_n
self.last_n = last_n
self.age = age
user1 = User("Jhone","Wrick","40")
And __call__ is called when you call the object like any other function.
Example:
class USER:
def __call__(self,arg):
"todo here"
print(f"I am in __call__ with arg : {arg} ")
user1=USER()
user1("One") #calling the object user1 and that's gonna call __call__ dunder functions
You can also use __call__ method in favor of implementing decorators.
This example taken from Python 3 Patterns, Recipes and Idioms
class decorator_without_arguments(object):
def __init__(self, f):
"""
If there are no decorator arguments, the function
to be decorated is passed to the constructor.
"""
print("Inside __init__()")
self.f = f
def __call__(self, *args):
"""
The __call__ method is not called until the
decorated function is called.
"""
print("Inside __call__()")
self.f(*args)
print("After self.f( * args)")
#decorator_without_arguments
def sayHello(a1, a2, a3, a4):
print('sayHello arguments:', a1, a2, a3, a4)
print("After decoration")
print("Preparing to call sayHello()")
sayHello("say", "hello", "argument", "list")
print("After first sayHello() call")
sayHello("a", "different", "set of", "arguments")
print("After second sayHello() call")
Output:
Case 1:
class Example:
def __init__(self, a, b, c):
self.a=a
self.b=b
self.c=c
print("init", self.a, self.b, self.c)
Run:
Example(1,2,3)(7,8,9)
Result:
- init 1 2 3
- TypeError: 'Example' object is not callable
Case 2:
class Example:
def __init__(self, a, b, c):
self.a=a
self.b=b
self.c=c
print("init", self.a, self.b, self.c)
def __call__(self, x, y, z):
self.x=x
self.y=y
self.z=z
print("call", self.x, self.y, self.z)
Run:
Example(1,2,3)(7,8,9)
Result:
- init 1 2 3
- call 7 8 9
Short and sweet answers are already provided above. I wanna provide some practical implementation as compared with Java.
class test(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def __call__(self, a, b, c):
self.a = a
self.b = b
self.c = c
instance1 = test(1, 2, 3)
print(instance1.a) #prints 1
#scenario 1
#creating new instance instance1
#instance1 = test(13, 3, 4)
#print(instance1.a) #prints 13
#scenario 2
#modifying the already created instance **instance1**
instance1(13,3,4)
print(instance1.a)#prints 13
Note: scenario 1 and scenario 2 seems same in terms of result output.
But in scenario1, we again create another new instance instance1. In scenario2,
we simply modify already created instance1. __call__ is beneficial here as the system doesn't need to create new instance.
Equivalent in Java
public class Test {
public static void main(String[] args) {
Test.TestInnerClass testInnerClass = new Test(). new TestInnerClass(1, 2, 3);
System.out.println(testInnerClass.a);
//creating new instance **testInnerClass**
testInnerClass = new Test().new TestInnerClass(13, 3, 4);
System.out.println(testInnerClass.a);
//modifying already created instance **testInnerClass**
testInnerClass.a = 5;
testInnerClass.b = 14;
testInnerClass.c = 23;
//in python, above three lines is done by testInnerClass(5, 14, 23). For this, we must define __call__ method
}
class TestInnerClass /* non-static inner class */{
private int a, b,c;
TestInnerClass(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
}
__init__ is a special method in Python classes, it is the constructor method for a class. It is called whenever an object of the class is constructed or we can say it initialises a new object.
Example:
In [4]: class A:
...: def __init__(self, a):
...: print(a)
...:
...: a = A(10) # An argument is necessary
10
If we use A(), it will give an error
TypeError: __init__() missing 1 required positional argument: 'a' as it requires 1 argument a because of __init__ .
........
__call__ when implemented in the Class helps us invoke the Class instance as a function call.
Example:
In [6]: class B:
...: def __call__(self,b):
...: print(b)
...:
...: b = B() # Note we didn't pass any arguments here
...: b(20) # Argument passed when the object is called
...:
20
Here if we use B(), it runs just fine because it doesn't have an __init__ function here.
We can use call method to use other class methods as static methods.
class _Callable:
def __init__(self, anycallable):
self.__call__ = anycallable
class Model:
def get_instance(conn, table_name):
""" do something"""
get_instance = _Callable(get_instance)
provs_fac = Model.get_instance(connection, "users")
I want to bring to the table some short cuts and syntax sugar, as well as few techniques that can be used, but I haven't see them in the current answers.
Instantiate the class and call it immediately
In many cases, for example when need to make a APi request, and the logic is encapsulated inside a class and what we really need is just give the data to that class and run it immediatelly as a separate entity, the instantiate class may not been needed. That is the
instance = MyClass() # instanciation
instance() # run the instance.__call__()
# now instance is not needed
Instead we can do something like that.
class HTTPApi:
def __init__(self, val1, val2):
self.val1 = val1
self.val2 = val2
def __call__(self, *args, **kwargs):
return self.run(args, kwargs)
def run(self, *args, **kwargs):
print("hello", self.val1, self.val2, args, kwargs)
if __name__ == '__main__':
# Create a class, and call it
(HTTPApi("Value1", "Value2"))("world", 12, 213, 324, k1="one", k2="two")
Give to call another existing method
We can declare a method to the __call__ as well, without creating an actual __call__ method.
class MyClass:
def __init__(self, val1, val2):
self.val1 = val1
self.val2 = val2
def run(self, *args, **kwargs):
print("hello", self.val1, self.val2, args, kwargs)
__call__ = run
if __name__ == '__main__':
(MyClass("Value1", "Value"))("world", 12, 213, 324, k1="one", k2="two")
This allows to declare another global function instead of a method, for whatever reason (there may be some reasons, for example you can't modify that method but you need it to be called by the class).
def run(self, *args, **kwargs):
print("hello",self.val1, self.val2, args, kwargs)
class MyClass:
def __init__(self, val1, val2):
self.val1 = val1
self.val2 = val2
__call__ = run
if __name__ == '__main__':
(MyClass("Value1", "Value2"))("world", 12, 213, 324, k1="one", k2="two")
call method is used to make objects act like functions.
>>> class A:
... def __init__(self):
... print "From init ... "
...
>>> a = A()
From init ...
>>> a()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: A instance has no __call__ method
<*There is no __call__ method so it doesn't act like function and throws error.*>
>>>
>>> class B:
... def __init__(self):
... print "From init ... "
... def __call__(self):
... print "From call it is a function ... "
...
>>> b = B()
From init ...
>>> b()
From call it is a function...
>>>
<* __call__ method made object "b" to act like function *>
We can also pass it to a class variable.
class B:
a = A()
def __init__(self):
print "From init ... "
__init__() can:
initialize the instance of class.
be called many time.
only return None.
__call__() can be freely used like an instance method.
For example, Person class has __init__() and __call__() as shown below:
class Person:
def __init__(self, f_name, l_name):
self.f_name = f_name
self.l_name = l_name
print('"__init__()" is called.')
def __call__(self, arg):
return arg + self.f_name + " " + self.l_name
Now, we create and initialize the instance of Person class as shown below:
# Here
obj = Person("John", "Smith")
Then, __init__() is called as shown below:
"__init__()" is called.
Next, we call __call__() in 2 ways as shown below:
obj = Person("John", "Smith")
print(obj("Hello, ")) # Here
print(obj.__call__("Hello, ")) # Here
Then, __call__() is called as shown below:
"__init__()" is called.
Hello, John Smith # Here
Hello, John Smith # Here
And, __init__() can be called many times as shown below:
obj = Person("John", "Smith")
print(obj.__init__("Tom", "Brown")) # Here
print(obj("Hello, "))
print(obj.__call__("Hello, "))
Then, __init__() is called and the instance of Person class is reinitialized and None is returned from __init__() as shown below:
"__init__()" is called.
"__init__()" is called. # Here
None # Here
Hello, Tom Brown
Hello, Tom Brown
And, if __init__() doesn't return None and we call __init__() as shown below:
class Person:
def __init__(self, f_name, l_name):
self.f_name = f_name
self.l_name = l_name
print('"__init__()" is called.')
return "Hello" # Here
# ...
obj = Person("John", "Smith") # Here
The error below occurs:
TypeError: __init__() should return None, not 'str'
And, if __call__ is not defined in Person class:
class Person:
def __init__(self, f_name, l_name):
self.f_name = f_name
self.l_name = l_name
print('"__init__()" is called.')
# def __call__(self, arg):
# return arg + self.f_name + " " + self.l_name
Then, we call obj("Hello, ") as shown below:
obj = Person("John", "Smith")
obj("Hello, ") # Here
The error below occurs:
TypeError: 'Person' object is not callable
Then again, we call obj.__call__("Hello, ") as shown below:
obj = Person("John", "Smith")
obj.__call__("Hello, ") # Here
The error below occurs:
AttributeError: 'Person' object has no attribute '__call__'

Categories

Resources