Organizing Fluent Interfaces in Python
Inspired by a recent post about fluid interfaces in PHP , I immediately wondered how to implement this in python easier and more beautiful (python is always simpler and more beautiful). I offer several ways in the order of receipt of thoughts.

To build a chain of operators, we need the function to return an instance of the class. This can be manually set.
Obviously, this approach works perfectly, but we are looking for a little more.
This is the first idea that came to mind. Define a decorator for methods in the class. We are very happy that the instance is passed as the first argument.
We simply mark with the decorator the functions that need to be used in the chain. The return value is ignored and a class instance is passed instead.
The method is clearly more readable - you can immediately see what functions you can use in the chain. However, usually the architectural approach extends to most class methods that are not interesting to mark one at a time.
We can check the return value when calling the function. In the absence of one, we transfer the object itself. We will do this through __getattribute__, intercepting any access to the methods and fields of the class. To begin with, we simply define a class with similar behavior, we will inherit all working classes from it.
If the method returns a value, it is passed. If not, then the class instance itself goes instead.
Now we do not need to modify the working class in any way except specifying the chaining class as one of the parent ones. The obvious drawback is that we cannot use __getattribute__ for our own purposes.
We can use the metaclass to organize the necessary wrapper of the working class. When initializing the latter, we will wrap __getattribute__ on the fly (and its absence does not bother us either).
It’s practically no different from the previous version - we only control the creation of __getattribute__ using a metaclass. To wrap the working class, just specify __metaclass__.
As you can see, the __getattribute__ originally available in the working class works. When inheriting from the working class, the behavior is preserved - __getattribute__ is also inherited. If the native __getattribute__ does not return anything (even an AttributeError), then we also return the object itself.
Although the ubiquitous use of fluid interfaces is doubtful, there are still instances when such structures will be appropriate. Say, image processing or any entities over which many operations are sequentially performed.
PS The last option, in my opinion, does not contain obvious shortcomings. If anyone can offer the best option - I will be glad to hear, as well as indications of my shortcomings.
PPS At the request of workers, links to the aforementioned article and description on Wikipedia
Update
Comrade davinchi rightly pointed out that wrap on every call is at least strange. Plus, we run a check every time we access the fields of the object.
Now we will process all the methods at once, but we will check the modification and creation of the methods in order to wrap them.
In addition to the fact that now we don’t wrap methods with every call (which gave a ~ 30% increase in speed), we also carry out the necessary checks not on every reading of the object’s fields, but on each record (which happens less often). If there is no entry, it works as fast as the decorator method.

The first way - in the forehead
To build a chain of operators, we need the function to return an instance of the class. This can be manually set.
def add(self,x):
self.val += x
return self
Obviously, this approach works perfectly, but we are looking for a little more.
The second way - decorators
This is the first idea that came to mind. Define a decorator for methods in the class. We are very happy that the instance is passed as the first argument.
def chained(fn):
def new(*args,**kwargs):
fn(*args,**kwargs)
return args[0]
return new
class UsefulClass1():
def __init__(self,val): self.val = val
@chained
def add(self,val): self.val += val
@chained
def mul(self,val): self.val *= val
We simply mark with the decorator the functions that need to be used in the chain. The return value is ignored and a class instance is passed instead.
>>> print UsefulClass1(10).add(5).mul(10).add(1).val
151
The method is clearly more readable - you can immediately see what functions you can use in the chain. However, usually the architectural approach extends to most class methods that are not interesting to mark one at a time.
The third way - automatic
We can check the return value when calling the function. In the absence of one, we transfer the object itself. We will do this through __getattribute__, intercepting any access to the methods and fields of the class. To begin with, we simply define a class with similar behavior, we will inherit all working classes from it.
from types import MethodType
class Chain(object):
def __getattribute__(self,item):
fn = object.__getattribute__(self,item)
if fn and type(fn)==MethodType:
def chained(*args,**kwargs):
ans = fn(*args,**kwargs)
return ans if ans!=None else self
return chained
return fn
class UsefulClass2(Chain):
val = 1
def add(self,val): self.val += val
def mul(self,val): self.val *= val
def third(self): return 386
If the method returns a value, it is passed. If not, then the class instance itself goes instead.
>>> print UsefulClass2().add(15).mul(16).add(-5).val
251
>>> print UsefulClass2().third()
386
Now we do not need to modify the working class in any way except specifying the chaining class as one of the parent ones. The obvious drawback is that we cannot use __getattribute__ for our own purposes.
The fourth method - Im So Meta ...
We can use the metaclass to organize the necessary wrapper of the working class. When initializing the latter, we will wrap __getattribute__ on the fly (and its absence does not bother us either).
from types import MethodType
class MetaChain(type):
def __new__(cls,name,bases,dict):
old = dict.get('__getattribute__',object.__getattribute__)
def new_getattribute(inst,val):
attr = old(inst,val)
if attr==None: return inst
if attr and type(attr)==MethodType:
def new(*args,**kwargs):
ans = attr(*args,**kwargs)
return ans if ans!=None else inst
return new
return attr
dict['__getattribute__'] = new_getattribute
return type.__new__(cls,name,bases,dict)
class UsefulClass3():
__metaclass__ = MetaChain
def __getattribute__(self,item):
if item=="dp": return 493
return object.__getattribute__(self,item)
val = 1
def add(self,val): self.val += val
def mul(self,val): self.val *= val
It’s practically no different from the previous version - we only control the creation of __getattribute__ using a metaclass. To wrap the working class, just specify __metaclass__.
>>> print UsefulClass3().dp
493
>>> print UsefulClass3().add(4).mul(5).add(1).mul(25).add(-1).val
649
As you can see, the __getattribute__ originally available in the working class works. When inheriting from the working class, the behavior is preserved - __getattribute__ is also inherited. If the native __getattribute__ does not return anything (even an AttributeError), then we also return the object itself.
Instead of a conclusion
Although the ubiquitous use of fluid interfaces is doubtful, there are still instances when such structures will be appropriate. Say, image processing or any entities over which many operations are sequentially performed.
PS The last option, in my opinion, does not contain obvious shortcomings. If anyone can offer the best option - I will be glad to hear, as well as indications of my shortcomings.
PPS At the request of workers, links to the aforementioned article and description on Wikipedia
Update
The fifth method - roast and hearth
Comrade davinchi rightly pointed out that wrap on every call is at least strange. Plus, we run a check every time we access the fields of the object.
Now we will process all the methods at once, but we will check the modification and creation of the methods in order to wrap them.
class NewMetaChain(type):
def __new__(cls,name,bases,dict):
old = dict.get('__setattr__',object.__setattr__)
def wrap(fn,inst=None):
def new(*args,**kwargs):
ans = fn(*args,**kwargs)
return ans if ans!=None else inst or args[0]
return new
special = dir(cls)
for item, fn in dict.items():
if item not in special and isinstance(fn,FunctionType):
dict[item] = wrap(fn)
def new_setattr(inst,item,val):
if isinstance(val,FunctionType):
val = wrap(val,inst)
return old(inst,item,val)
dict['__setattr__'] = new_setattr
return type.__new__(cls,name,bases,dict)
class UsefulClass4():
__metaclass__ = NewMetaChain
def __setattr__(self,item,val):
if val == 172: val = "giza"
object.__setattr__(self, item, val)
val = 1
def add(self,val): self.val += val
def mul(self,val): self.val *= val
def nul(self): pass
In addition to the fact that now we don’t wrap methods with every call (which gave a ~ 30% increase in speed), we also carry out the necessary checks not on every reading of the object’s fields, but on each record (which happens less often). If there is no entry, it works as fast as the decorator method.