Is it possible to override a class' __call__ method? [duplicate] - python

This question already has answers here:
Overriding special methods on an instance
(5 answers)
Closed 3 years ago.
I need to change the behavior of the __call__ method of a given object. The naive approach would be something like:
class A(object):
def __call__(self):
return 1
def new_call():
return 42
a = A()
a.__call__ = new_call
Why is it not the output of a() 42? Is there a workaround I can exploit to achieve the same effect? (without using the class)
============================ EDIT =================================
For the records, the short answer is no. Python calls the "special methods" like __call_ directly on the class and not on the instance, therefore if you need to change the method, you need to change it on the class itself.

Special methods (aka "dunder" methods) are looked-up with respect to the class of the object, so to override it you would need to change the class, not the instance. Also note that methods all have an initial argument passed to them, usually called self.
The following would do what you want (notice how that it affects all instances of the class):
class A(object):
def __call__(self):
return 1
def new_call(self):
return 42
a1 = A()
a2 = A()
A.__call__ = new_call
print(a1()) # -> 42
print(a2()) # -> 42
If you only want to change a specific instance, a relatively simple workaround is to make the class' __call_() method call one that's not "special" like it is — i.e. by introducing a level of indirection.
Here's what I mean:
# Workaround
class B(object):
def __call__(self):
return self.call_method(self)
#staticmethod
def call_method(self):
return 1
def new_call(self):
return 42
# Create two instances for testing.
b1 = B()
b2 = B()
b2.call_method = new_call # Will only affect this instance.
print(b1()) # -> 1
print(b2()) # -> 42

Typically, special method names, such as __call__, are accessed via the object's type, rather than the instance's attribute collection. From Special Method Names:
If a class defines a method named __getitem__(), and x is an instance of this class, then x[i] is roughly equivalent to type(x).__getitem__(x, i).
This also applies to __call__. a() is roughly equivalent to type(a).__call__(a). Changing a's __call__ attribute doesn't have an effect, because the code is looking for A's __call__ attribute.
Assigning a new function to A.__call__ should do what you want.
class A(object):
def __call__(self):
return 1
def new_call(self):
return 42
a = A()
A.__call__ = new_call
print(a())
Result:
42

Because A.__call__ is resolved before a.__call__. If you want to bind __call__ per instance, then you have to change the resolution by attempting to resolve it from there. E.g.
class A(object):
def __call__(self):
try:
return vars(self)['__call__']()
except KeyError:
return 1
def new_call():
return 42
a = A()
print(a())
a.__call__ = new_call
print(a())
Would prints:
1
42
If you want it to be a method, and have access to self, then you have to bind it. E.g.
from types import MethodType
class A(object):
def __call__(self):
try:
return vars(self)['__call__']()
except KeyError:
return 1
def new_call_method(self):
return self
a = A()
a.__call__ = MethodType(new_call_method, a)
also_a = a()
Would return a.

Related

How to have multiple inits for a class

I want to create a class called Chain.
I want to be able to call __init__ method multiple times.
For example:
>> Chain(1)
1
>> Chain(1)(2)
3
How can I do this in Python?
You just need a callable int:
>>> class Chain(int):
... def __call__(self, other: int) -> Chain:
... return Chain(self + other)
...
>>> Chain(10) == 10
True
>>> Chain(1)(2)(3)
6
To do exactly what you have shown (the usefulness of which I question), you need to override __repr__ and define __call__. For example,
class Chain:
def __init__(self, x):
self.x = x
def __repr__(self):
return repr(self.x)
def __call__(self, x):
return Chain(self.x + x)
Since __call__ returns a new instance of Chain, you can chain calls indefinitely.
>>> Chain(1)
1
>>> Chain(1)(2)
3
>>> Chain(1)(2)(3)
6
Chain itself will always return an instance of Chain (unless you define Chain using a metaclass other than the default of type). Chain.__call__ is what allows you to call an instance of Chain like a function, returning a function to allow the actual chain of calls to continue. __repr__ is used so that each attempt to "show" the instance produces the value of its attribute.
As far as I know, you cannot implement multiple __inits__ since it's the function which initializes variables etc.
What you can do is implement the __call__ function, which is the one being called when you call an instance e.g
class MyClass:
def __init__(self,a):
self.a = a
print("Init")
def __call__(self,b):
print("call")
self.b=b
inst = MyClass(1) # "Init"
inst(2) #"call"
Does this answer your question?
class Chain:
def __init__(self, value):
self.value = value
def __call__(self, value):
return Chain(self.value + value)
one = Chain(1)
three = Chain(1)(2)
print(three.value)
Just to explain what __call__ does is:
call is method enables Python programmers to write classes where the instances
behave like functions and can be called like a function.

Is there a way to pass a function call to an inner object?

Is there a way in python to pass a function call to an inner object, maybe through a decorator or wrapper? In the example below, class A holds a list of class B objects, and one of the class B objects is selected as the active object. I want class A to function as a passthrough, just identifying which of the class B objects that the call goes to. However, class A doesn't know what type of class it is going to hold beforehand, so I can't just add a set_var function to class A. It has to work for any generic function that class B has. It will only have one type of class in its objects list, so it could take class B as an input when it is instantiated and dynamically create functions, if that's a possibility. The client wouldn't know whether it's dealing with class A or class B. The code below is as far as I got.
class A:
def __init__(self):
self.objects = []
self.current_object = 0
def add_object(self, object):
self.objects.append(object)
class B:
def __init__(self):
self.var = 10
def set_var(self, new_var):
self.var = new_var
a_obj = A()
b_obj1 = B()
b_obj2 = B()
a_obj.add_object(b_obj1)
a_obj.add_object(b_obj2)
a_obj.set_var(100)
You could use the generic __getattr__ to delegate to the wrapped object.
class A:
def __init__(self):
self.objects = []
self.current_object = 0
def add_object(self, obj):
self.objects.append(obj)
self.current_object = obj
def __getattr__(self, name):
return getattr(self.current_object, name)
class B:
def __init__(self):
self.var = 10
def set_var(self, new_var):
self.var = new_var
a_obj = A()
b_obj1 = B()
b_obj2 = B()
a_obj.add_object(b_obj1)
a_obj.add_object(b_obj2)
a_obj.set_var(100)
print(b_obj2.var)
That will print "100".
You will still get an AttributeError if the wrapped object doesn't have the expected method.
It was interesting to look at this, it is intentionally rough but it does indeed allow you to call one the B instance's set_var methods.
The code below uses sets as a quick and dirty way to see the difference in callable methods, and if there is; it sets the attribute based on that name. Binding the method to the A instance.
This would only bind set_var once from the first object given.
def add_object(self, object):
self.objects.append(object)
B_methods = set([m for m in dir(object) if callable(getattr(object, m))])
A_methods = set([m for m in dir(self) if callable(getattr(self, m))])
to_set = B_methods.difference(A_methods)
for method in to_set:
setattr(self, method, getattr(object, method))

Python: Class private attributes [duplicate]

I am generally confused about the difference between a "property" and an "attribute", and can't find a great resource to concisely detail the differences.
Properties are a special kind of attribute. Basically, when Python encounters the following code:
spam = SomeObject()
print(spam.eggs)
it looks up eggs in spam, and then examines eggs to see if it has a __get__, __set__, or __delete__ method — if it does, it's a property. If it is a property, instead of just returning the eggs object (as it would for any other attribute) it will call the __get__ method (since we were doing lookup) and return whatever that method returns.
More information about Python's data model and descriptors.
With a property you have complete control on its getter, setter and deleter methods, which you don't have (if not using caveats) with an attribute.
class A(object):
_x = 0
'''A._x is an attribute'''
#property
def x(self):
'''
A.x is a property
This is the getter method
'''
return self._x
#x.setter
def x(self, value):
"""
This is the setter method
where I can check it's not assigned a value < 0
"""
if value < 0:
raise ValueError("Must be >= 0")
self._x = value
>>> a = A()
>>> a._x = -1
>>> a.x = -1
Traceback (most recent call last):
File "ex.py", line 15, in <module>
a.x = -1
File "ex.py", line 9, in x
raise ValueError("Must be >= 0")
ValueError: Must be >= 0
In general speaking terms a property and an attribute are the same thing. However, there is a property decorator in Python which provides getter/setter access to an attribute (or other data).
class MyObject(object):
# This is a normal attribute
foo = 1
#property
def bar(self):
return self.foo
#bar.setter
def bar(self, value):
self.foo = value
obj = MyObject()
assert obj.foo == 1
assert obj.bar == obj.foo
obj.bar = 2
assert obj.foo == 2
assert obj.bar == obj.foo
The property allows you to get and set values like you would normal attributes, but underneath there is a method being called translating it into a getter and setter for you. It's really just a convenience to cut down on the boilerplate of calling getters and setters.
Lets say for example, you had a class that held some x and y coordinates for something you needed. To set them you might want to do something like:
myObj.x = 5
myObj.y = 10
That is much easier to look at and think about than writing:
myObj.setX(5)
myObj.setY(10)
The problem is, what if one day your class changes such that you need to offset your x and y by some value? Now you would need to go in and change your class definition and all of the code that calls it, which could be really time consuming and error prone. The property allows you to use the former syntax while giving you the flexibility of change of the latter.
In Python, you can define getters, setters, and delete methods with the property function. If you just want the read property, there is also a #property decorator you can add above your method.
http://docs.python.org/library/functions.html#property
I learnt 2 differences from site of Bernd Klein, in summary:
1. A property is a more convenient way to achieve data encapsulation
For example, let's say you have a public attribute length. Later on, your project requires you to encapsulate it, i.e. to change it to private and provide a getter and setter => you have to change the the code you wrote before:
# Old code
obj1.length = obj1.length + obj2.length
# New code (using private attributes and getter and setter)
obj1.set_length(obj1.get_length() + obj2.get_length()) # => this is ugly
If you use #property and #length.setter => you don't need to change that old code.
2. A property can encapsulate multiple attributes
class Person:
def __init__(self, name, physic_health, mental_health):
self.name = name
self.__physic_health = physic_health
self.__mental_health = mental_health
#property
def condition(self):
health = self.__physic_health + self.__mental_health
if(health < 5.0):
return "I feel bad!"
elif health < 8.0:
return "I am ok!"
else:
return "Great!"
In this example, __physic_health and __mental_health are private and cannot be accessed directly from outside.
There is also one not obvious difference that i use to cache or refresh data , often we have a function connected to class attribute. For instance i need to read file once and keep content assigned to the attribute so the value is cached:
class Misc():
def __init__(self):
self.test = self.test_func()
def test_func(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
Output:
func running
func value
func value
We accessed the attribute twice but our function was fired only once. Changing the above example to use property will cause attribute's value refresh each time you access it:
class Misc():
#property
def test(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
Output:
func running
func value
func running
func value
I like to think that, if you want to set a restriction for an attribute, use a property.
Although all attributes are public, generally programmers differentiate public and private attributes with an underscore(_). Consider the following class,
class A:
def __init__(self):
self.b = 3 # To show public
self._c = 4 # To show private
Here, b attribute is intended to be accessed from outside class A. But, readers of this class might wonder, can b attribute be set from outside class A?
If we intend to not set b from outside, we can show this intention with #property.
class A:
def __init__(self):
self._c = 4 # To show private
#property
def b(self):
return 3
Now, b can't be set.
a = A()
print(a.b) # prints 3
a.b = 7 # Raises AttributeError
Or, if you wish to set only certain values,
class A:
#property
def b(self):
return self._b
#b.setter
def b(self, val):
if val < 0:
raise ValueError("b can't be negative")
self._b = val
a = A()
a.b = 6 # OK
a.b = -5 # Raises ValueError

Class method as a decorator

I have a class where I have multiple methods. I want to use one of the methods as a decorator for other methods. For this I am using following syntax:
#self.action
def execute(self,req):
where action is other method in my class. But it doesn't work and throws exception as
name 'self' is not defined
You cannot use a method of the class while defining it; there is no self within the class nor is the class 'baked' yet to even access any class.
You can treat methods as functions to use as a decorator:
class SomeClass():
def action(func):
# decorate
return wrapper
#action
def execute(self, req):
# something
If action is defined on a base class, then you'd have to refer to the name via the base class:
class Base():
#staticmethod
def action(func):
# decorate
return wrapper
class Derived(Base):
#Base.action
def execute(self, req):
# something
For Python 2, you'd have to make action a static method here, as otherwise you get an unbound method that'll complain you cannot call it without an instance as the first argument. In Python 3, you can leave off the #staticmethod decorator there, at least for the purposes of the decorator.
But note that action cannot then be used as a method directly; perhaps it should not be part of the class at all at that point. It is not part of the end-user API here, presumably the decorator is not used by consumers of the instances of these classes.
Just beware that both the decorator and the decorated function are unbound methods, so you can only access the self (or cls for classmethods) in the inner scope of the decorator, and must manually bind the decorated method to the instance bound in the inner decorator.
class A:
x = 5
y = 6
def decorate(unbound):
def _decorator(self):
bound = unbound.__get__(self)
return bound() * self.x
return _decorator
#decorate
def func(self):
return self.y
A().func() # 30!!
Still trying to wrap my head around how decorators could be inherited and overridden.
Beware that for the decorator to work it can't be bound to an instance. That is: there is no way to make this work
a = A()
#a.decorate
def func(*args):
return 1
Despite this pattern is much more common than the asked here.
At this point the question raises: is it a method at all or just code that you happen to hide in a class?
The only way to prevent the decorator being wrongfully bound is to declare it as a staticmethod, but then it must be in a previous super class because to be used it must be bound to the static class reference which would not be yet defined, just as the self.
class A:
x = 1
#staticmethod
def decorate(unbound):
def _decorator(self):
bound = unbound.__get__(self)
return bound() * self.x
return _decorator
class B(A):
#A.decorate
def func(self):
return 1
class C():
x = 2
#B.decorate
def func(self):
return 1
a = A()
class D():
x = 3
#a.decorate
def func(self):
return 1
B().func() # 1
C().func() # 2
D().func() # 3
But as you can see, there is no way for the decorator to use the state of its own class. class A from this last example just happens to be a mixin with a default x variable and an "unrelated" static decorator.
So, again, is it a method?
To overcome all of this, you can bind the staticmethod in your same class to an arbitrary type. Namely, the builtin type will do.
class A:
x = 1
#staticmethod
def decorate(unbound):
def _decorator(self):
bound = unbound.__get__(self)
return bound() * self.x
return _decorator
#decorate.__get__(type)
def func(self):
return 1
class B:
x = 2
#A.decorate
def func(self):
return 1
class C:
x = 3
#(A().decorate) # Only for Python 3.9+, see PEP-614
def func(self):
return 1
A().func() # 1
B().func() # 2
C().func() # 3
But this features too much magic for my taste. And still not a method for my gut.
In python "self" is passed to instance methods as an argument (the first), "self" is just a convention is possible to call it "foobarbaz" (of course it would be silly)… the point is that, from the outside "self" is not defined (because its scope is the method)… you can't decorate class methods with other class methods, instead you have to write a separate class!

What's the difference between a Python "property" and "attribute"?

I am generally confused about the difference between a "property" and an "attribute", and can't find a great resource to concisely detail the differences.
Properties are a special kind of attribute. Basically, when Python encounters the following code:
spam = SomeObject()
print(spam.eggs)
it looks up eggs in spam, and then examines eggs to see if it has a __get__, __set__, or __delete__ method — if it does, it's a property. If it is a property, instead of just returning the eggs object (as it would for any other attribute) it will call the __get__ method (since we were doing lookup) and return whatever that method returns.
More information about Python's data model and descriptors.
With a property you have complete control on its getter, setter and deleter methods, which you don't have (if not using caveats) with an attribute.
class A(object):
_x = 0
'''A._x is an attribute'''
#property
def x(self):
'''
A.x is a property
This is the getter method
'''
return self._x
#x.setter
def x(self, value):
"""
This is the setter method
where I can check it's not assigned a value < 0
"""
if value < 0:
raise ValueError("Must be >= 0")
self._x = value
>>> a = A()
>>> a._x = -1
>>> a.x = -1
Traceback (most recent call last):
File "ex.py", line 15, in <module>
a.x = -1
File "ex.py", line 9, in x
raise ValueError("Must be >= 0")
ValueError: Must be >= 0
In general speaking terms a property and an attribute are the same thing. However, there is a property decorator in Python which provides getter/setter access to an attribute (or other data).
class MyObject(object):
# This is a normal attribute
foo = 1
#property
def bar(self):
return self.foo
#bar.setter
def bar(self, value):
self.foo = value
obj = MyObject()
assert obj.foo == 1
assert obj.bar == obj.foo
obj.bar = 2
assert obj.foo == 2
assert obj.bar == obj.foo
The property allows you to get and set values like you would normal attributes, but underneath there is a method being called translating it into a getter and setter for you. It's really just a convenience to cut down on the boilerplate of calling getters and setters.
Lets say for example, you had a class that held some x and y coordinates for something you needed. To set them you might want to do something like:
myObj.x = 5
myObj.y = 10
That is much easier to look at and think about than writing:
myObj.setX(5)
myObj.setY(10)
The problem is, what if one day your class changes such that you need to offset your x and y by some value? Now you would need to go in and change your class definition and all of the code that calls it, which could be really time consuming and error prone. The property allows you to use the former syntax while giving you the flexibility of change of the latter.
In Python, you can define getters, setters, and delete methods with the property function. If you just want the read property, there is also a #property decorator you can add above your method.
http://docs.python.org/library/functions.html#property
I learnt 2 differences from site of Bernd Klein, in summary:
1. A property is a more convenient way to achieve data encapsulation
For example, let's say you have a public attribute length. Later on, your project requires you to encapsulate it, i.e. to change it to private and provide a getter and setter => you have to change the the code you wrote before:
# Old code
obj1.length = obj1.length + obj2.length
# New code (using private attributes and getter and setter)
obj1.set_length(obj1.get_length() + obj2.get_length()) # => this is ugly
If you use #property and #length.setter => you don't need to change that old code.
2. A property can encapsulate multiple attributes
class Person:
def __init__(self, name, physic_health, mental_health):
self.name = name
self.__physic_health = physic_health
self.__mental_health = mental_health
#property
def condition(self):
health = self.__physic_health + self.__mental_health
if(health < 5.0):
return "I feel bad!"
elif health < 8.0:
return "I am ok!"
else:
return "Great!"
In this example, __physic_health and __mental_health are private and cannot be accessed directly from outside.
There is also one not obvious difference that i use to cache or refresh data , often we have a function connected to class attribute. For instance i need to read file once and keep content assigned to the attribute so the value is cached:
class Misc():
def __init__(self):
self.test = self.test_func()
def test_func(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
Output:
func running
func value
func value
We accessed the attribute twice but our function was fired only once. Changing the above example to use property will cause attribute's value refresh each time you access it:
class Misc():
#property
def test(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
Output:
func running
func value
func running
func value
I like to think that, if you want to set a restriction for an attribute, use a property.
Although all attributes are public, generally programmers differentiate public and private attributes with an underscore(_). Consider the following class,
class A:
def __init__(self):
self.b = 3 # To show public
self._c = 4 # To show private
Here, b attribute is intended to be accessed from outside class A. But, readers of this class might wonder, can b attribute be set from outside class A?
If we intend to not set b from outside, we can show this intention with #property.
class A:
def __init__(self):
self._c = 4 # To show private
#property
def b(self):
return 3
Now, b can't be set.
a = A()
print(a.b) # prints 3
a.b = 7 # Raises AttributeError
Or, if you wish to set only certain values,
class A:
#property
def b(self):
return self._b
#b.setter
def b(self, val):
if val < 0:
raise ValueError("b can't be negative")
self._b = val
a = A()
a.b = 6 # OK
a.b = -5 # Raises ValueError

Categories