call method without parenthesis in python [duplicate] - python

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

Related

Catch if someone tries to set a class instance's variable directly [duplicate]

This question already has answers here:
What's the pythonic way to use getters and setters?
(8 answers)
Closed 2 years ago.
Assume that I have a class which requires pre-treatment of an input variable x. Towards this end, I have implemented a function within this class to set the variable (including the pre-treatment). To fool-proof the algorithm, I would like to know whether there is a way to catch attempts of users trying to set x manually, instead of calling the correct function. As a small dummy example, consider the following:
class dummy():
def __init__(self, x):
# This function initializes the instance
self.x = x
def adjust_x(self):
# This function makes some change to x
self.x += 5
def set_x(self, x):
# This function initializes x correctly
self.x = x
self.adjust_x()
instance = dummy(3)
print('Initialized correctly, the value of x is: ' + str(instance.x))
# We can also set x later on, using the correct function
instance.set_x(3)
print('Calling the function to set x, we get: ' + str(instance.x))
# However, if the user would try to set x directly, the variable does not get
# correctly adjusted:
instance.x = 3
print('Direct setting: ' + str(instance.x) + ' (/= 8, because instance.adjust_x() was not called)')
Is there a way to catch someone using instance.x to set x? I'd like to raise an error or a warning in that situation.
In Python, you can restrict the access of an attribute (that's the equivalent of setting the access modifier of a field to private) by prepending a double underscore to the attribute.
Example
class Object():
def __init__(self, name):
self.__name = name
Trying to access instance.name or instance.__name would raise an AttributeError.
Note
As #mkrieger1 pointed out, the double underscores were not meant to prevent access but I find it that it works. More about private variables in Python can be found here.

__call__ behavior [duplicate]

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()

How to instantiate a class given its name as a string? [duplicate]

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 8 years ago.
Give some class definitiona in python, e.g.
class A(object):
def __init__(self):
self.x = 5
class B(object):
def __init(self):
self.x = 42
I want to instantiate one of these classes given its name as string. So for example, if classname is A, then I want to do something like
myinstance = SOMETHING(classname)
which should correspond to
myinstance = A()
Is there a way to do this without the use of eval eval or maps? If not, I would do the following:
map = {'A': A, 'B': B}
myinstance = map[classname]()
Considering that the Python naming scheme is based on maps, you will be using maps of one sort or another even if you use eval.
Building your own map is the most appropriate, but you can also use globals() or retrieve it from a module if your classes are stored somewhere else:
import util_module
getattr(util_module, 'A') ()

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.

How to apply __str__ function when printing a list of objects in Python [duplicate]

This question already has answers here:
How to print instances of a class using print()?
(12 answers)
Closed 7 months ago.
Well this interactive python console snippet will tell everything:
>>> class Test:
... def __str__(self):
... return 'asd'
...
>>> t = Test()
>>> print(t)
asd
>>> l = [Test(), Test(), Test()]
>>> print(l)
[__main__.Test instance at 0x00CBC1E8, __main__.Test instance at 0x00CBC260,
__main__.Test instance at 0x00CBC238]
Basically I would like to get three asd string printed when I print the list. I have also tried pprint but it gives the same results.
Try:
class Test:
def __repr__(self):
return 'asd'
And read this documentation link:
The suggestion in other answers to implement __repr__ is definitely one possibility. If that's unfeasible for whatever reason (existing type, __repr__ needed for reasons other than aesthetic, etc), then just do
print [str(x) for x in l]
or, as some are sure to suggest, map(str, l) (just a bit more compact).
You need to make a __repr__ method:
>>> class Test:
def __str__(self):
return 'asd'
def __repr__(self):
return 'zxcv'
>>> [Test(), Test()]
[zxcv, zxcv]
>>> print _
[zxcv, zxcv]
Refer to the docs:
object.__repr__(self)
Called by the repr() built-in function and by string conversions (reverse quotes) to compute the “official” string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment). If this is not possible, a string of the form <...some useful description...> should be returned. The return value must be a string object. If a class defines __repr__() but not __str__(), then __repr__() is also used when an “informal” string representation of instances of that class is required.
This is typically used for debugging, so it is important that the representation is information-rich and unambiguous.

Categories