> I agree. I think of this as a functor pattern: object that supports some params being bound at constructor time, and other params set when the function is called later.
> Another perspective of the whole thing is that you have a function with many arguments, then you curry to bind some arguments, then pass the resulting function with remaining free arguments to be called.
It's not the same, though, because a socket etc is being constructed in the constructor. Here's an abridged (and possibly wrong!) version of a monitoring client:
class Monitor:
def __init__(self, monitoring_url, app_name):
self.monitoring_url = monitoring_url
self.session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=1))
self.details = ujson.dumps({'app_name': app_name, 'pid': os.getpid()})
async def send(self):
async with self.session.post(monitoring_url, data=self.details, raise_for_status=True) as resp:
pass
If you treat that as currying, you will create a new ClientSession every time you call ping(). A ClientSession contains a connection pool, so that means you will create a new socket instead of reusing one.
> In languages that let you operator overload function call syntax, you end up with an object that, once constructed, supports being called like with same syntax as a function call. This works easily in python (define __init__ and __call__ ), and you don't have to fight the typesystem to structure code that will accept both a callable object or a function.
In Python and Java, you can easily refer to bound methods to produce callables from objects, so this seems like unnecessary work.