__call__ behavior [duplicate] - python

This question already has answers here:
What is the difference between __init__ and __call__?
(17 answers)
Closed 3 years ago.
I don't understand the behavior of __call__:
class Filter:
def __init__(self, before, after, source):
self.filter = {}
self.filter['before:'] = before
self.filter['after:'] = after
self.filter['source:'] = source
def __call__(self):
return ' AND '.join([key + value for key, value in self.filter.items()])
When I call the instance, __call__ is not executed:
print(Filter(before='today', after='yesterday', source='web'))
returns <__main__.Filter object at 0x103f2bf10>
while
print(Filter(before='today', after='yesterday', source='web').__call__())
does what I want and returns what is defined in __call__(): before:today AND after:yesterday AND source:web
Why is this happening? Do I need to create an empty object first, then instantiate it, to make __call__ work?

In Filter(before='today', after='yesterday', source='web'), you don't call an instance, you create one. When you print it, you get the default representation for an instance of class Filter: <__main__.Filter object at 0x103f2bf10>
You need to create the instance first, then call it:
filter = Filter(before='today', after='yesterday', source='web')
filter()
Output:
'before:today AND after:yesterday AND source:web'
There is no need to explicitely use <your instance>.__call__(), just use the parentheses like you would do for any function.

Filter(...) does not "call" the instance, it creates it. To call, use the call syntax on the resulting object:
>>> Filter(...)()
or
>>> filt = Filter(...)
>>> filt()

Related

TypeError: __init__() missing 1 required positional argument: 'lists'

I created a class, something like below -
class child:
def __init__(self,lists):
self.myList = lists
def find_mean(self):
mean=np.mean(self.myList)
return mean
and when I create an onject something like below -
obj=child()
it gives the error -
TypeError: __init__() missing 1 required positional argument: 'lists'
if I create object like below then it works well -
obj=child([44,22,55)
or If I create the class like below -
class child:
def find_mean(self,myList):
mean=np.mean(myList)
return mean
and then I create the object like below -
obj=child()
then also it works well, however I need to make it in the way I explained in the very begining. Can you please help me understand this context?
In the first example, the __init__ method expects two parameters:
self is automatically filled in by Python.
lists is a parameter which you must give it. It will try to assign this value to a new variable called self.myList, and it won't know what value it is supposed to use if you don't give it one.
In the second example, you have not written an __init__ method. This means that Python creates its own default __init__ function which will not require any parameters. However, the find_mean method now requires you to give it a parameter instead.
When you say you want to create it in the way you explained at the beginning, this is actually impossible: the class requires a value, and you are not giving it one.
Therefore, it is hard for me to tell what you really want to do. However, one option might be that you want to create the class earlier, and then add a list to it later on. In this case, the code would look like this:
import numpy as np
class Child:
def __init__(self, lists=None):
self.myList = lists
def find_mean(self):
if self.myList is None:
return np.nan
mean = np.mean(self.myList)
return mean
This code allows you to create the object earlier, and add a list to it later. If you try to call find_mean without giving it a list, it will simply return nan:
child = Child()
print(child.find_mean()) # Returns `nan`
child.myList = [1, 2, 3]
print(child.find_mean()) # Returns `2`
the code you have at the top of your question defines a class called child, which has one attribute, lists, which is assigned at the time of instance creation in the __init__ method. This means that you must supply a list when creating an instance of child.
class child:
def __init__(self, lists):
self.myList = lists
def find_mean(self):
mean=np.mean(self.myList)
return mean
# works because a list is provided
obj = child([44,22,55])
# does not work because no list is given
obj = child() # TypeError
If you create the class like in your second example, __init__ is no longer being explicitly specified, and as such, the object has no attributes that must be assigned at instance creation:
class child:
def find_mean(self, myList):
mean=np.mean(myList)
return mean
# does not work because `child()` does not take any arguments
obj = child([44,22,55]) # TypeError
# works because no list is needed
obj = child()
The only way to both have the myList attribute, and not need to specify it at creation would be to assign a default value to it:
class child:
def find_mean(self,myList=None):
mean=np.mean(myList)
return mean
# now this will work
obj = child()
# as will this
obj = child([24, 35, 27])

call method without parenthesis in python [duplicate]

This question already has answers here:
What's the pythonic way to use getters and setters?
(8 answers)
Closed last month.
what modification i would need to do in the below function computeDifference to get result printed in the console, instead of object message.
i know i need to add parenthesis () to call function to get the result printed in the console, but is there any other way to print the result?
class Difference1:
def __init__(self, a):
self.__elements = a
def computeDifference(self):
self.difference = max(self.__elements)- min(self.__elements)
return self.difference
a = [5,8,9,22,2]
c = Difference1(a)
print(c.computeDifference)
Make it a property
class Difference1:
#property
def computeDifference(self):
...
print(c.computeDifference)
However, I would change the name to difference. The idea of a property is that you shouldn't know or care whether the value is computed at that time or is stored as an attribute of the object. See uniform access principle.
You could add a magic function:
class Difference1:
...
def __str__(self):
return str(self.computeDifference())
...
>>> a = [5,8,9,22,2]
>>> c = Difference1(a)
>>> print(c)
20

Have a Function Take a Variable Name of an Object [duplicate]

This question already has answers here:
How to access (get or set) object attribute given string corresponding to name of that attribute
(3 answers)
Closed 4 years ago.
If I have the following code:
class foo:
def __init__(self):
self.w = 5
self.z = 10
def sum(obj,x,y):
return obj.x+obj.y
f = foo()
print sum(foo,'x','y')
How would I create a function that takes in two unkown variable names and returns the sum of those variables variables?
In this case the example should print 15.
EDIT:
Typo for the last line it should say print sum(foo,'w','z')
All (I think?) python objects have a built-in __getattribute__ method. Use it like this:
def sum(obj,x,y):
return obj.__getattribute__(x)+obj.__getattribute__(y)
The method takes a string, and "unpacks" it to being a variable name.

Understanding classes 'self' [duplicate]

This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Closed 6 years ago.
In the following example employee is not used in the __init__ function, but we used it in the add_employee function calling self.employee.append().
Why is that? Why did we use self.employee.append() instead of employee.append() ? I thought we only use self for variables in the __init__ function.
class Workers():
employee = []
def __init__(self, name):
self.name = name
self.skills = []
self.add_employee()
def add_employee(self):
self.employee.append(self.name)
print('{} added to list'.format(self.name))
employee, __init__, and add_employee are just attributes of the class Workers.
employee is an attribute being a list, and __init__ is another attribute, being a method.
Also from the [def documentation](
https://docs.python.org/3/reference/compound_stmts.html#grammar-token-funcdef):
A function definition is an executable statement. Its execution binds the function name in the current local namespace to a function object (a wrapper around the executable code for the function).
so employees and __init__ and all other methods are really the same: names in a namespaces.
See also
https://docs.python.org/3/tutorial/classes.html#class-objects
The employee object is a class variable, not an instance variable. This means it is shared across all instances of that class. You can access it with classname.classvariablename or instancename.classvariablename. If you reassign an instance's version of it with something like instancename.classvariablename = newvalue, that instance will have a new instance variable of that name that masks its access to the class variable with the self reference (i.e., you won't be able to do instancename.classvariablename to get the class variable), but other instances - and the class - will still be able to (i.e., classname.classvariable will still work, and otherinstancename.classvariable will still point to that class variable). The following example demonstrates this.
>>> class A:
... l = []
...
>>> a = A()
>>> b = A()
>>> a.l
[]
>>> A.l
[]
>>> a.l = 3
>>> b.l
[]
>>> b.l.append(1)
>>> b.l
[1]
>>> A.l
[1]
>>> a.l
3

How to assign cache to a method in an OOP fashion? [duplicate]

This question already has answers here:
What is memoization and how can I use it in Python?
(14 answers)
Closed 9 years ago.
Suppose that I have class A and this class has a method called function. Can I assign a cache as a property to this method? In the sense that I could call it like a property?
class A:
def __init__(self,value):
self.value=value
def function(self,a):
"""function returns a+1 and caches the value for future calls."""
cache=[]
cache.append([a,a+1])
return a+1;
a=A(12)
print a.function(12)
print a.function.cache
Which gives me the error:
AttributeError: 'function' object has no attribute 'cache'
I know it is possible to assign a cache to the main class but I am looking for a possible way of assigning it as a property to the method object.
class A:
def __init__(self,value):
self.value=value
self.cache = {}
def function(self,a):
"""function returns a+1 and caches the value for future calls."""
# Add a default value of empty string to avoid key errors,
# check if we already have the value cached
if self.cache.get(a,''):
return self.cache[a]
else:
result = a + 1
self.cache[a] = result
return result
As far as I know there is no way of having the cache as a property of the method. Python doesn't have such a feature. But I think perhaps this solution will satisfy your needs.
EDIT
Upon further research, there is indeed a way to do this in Python 3
class A:
def __init__(self,value):
self.value=value
def function(self,a):
"""function returns a+1 and caches the value for future calls."""
# Add a default value of empty string to avoid key errors,
# check if we already have the value cached
if self.function.cache.get(a,''):
return self.function.cache[a]
else:
result = a + 1
self.function.cache[a] = result
return result
function.cache = {}
a=A(12)
print(a.function(12))
print(a.function.cache)
This is because in Python 3 instance methods are just functions. BTW in Python 2 it is indeed possible to add attributes to functions, but not to instance methods. If you need to use Python 2 then there is a solution to your problem involving decorators that you should look into.

Categories