[Python-ideas] __before__ and __after__ attributes for functions

David Townshend aquavitae69 at gmail.com
Thu Jan 23 10:27:55 CET 2014


On Thu, Jan 23, 2014 at 11:17 AM, Suresh V. <suresh_vv at yahoo.com> wrote:

> On Thursday 23 January 2014 02:22 PM, David Townshend wrote:
>
>> Maybe I'm missing something, but what's the use case, and why aren't
>> plain old decorators suitable?
>>
>
> May be they are.
>
> Let us say I want to alter the way the smtplib.SMTP.sendmail method works.
> I would like it to call a function that I define.I can then add this
> function to the __before__ attribute of this library function.
>
> Can this be done with decorators?
>

Not a decorator, but you can monkey patch it:

    @wraps(smtplib.SMTP.sendmail)
    def sendmail(*args, **kwargs):
        other_function()
        return smtplib.SMPT.sendmail(*args, **kwargs)

    smtplib.SMTP.sendmail = sendmail

But I still don't see a good reason for using __before__ rather than the
above, other than slightly less typing.  In a specific project there might
be a lot of this going on and brevity would be justifiable, but in that
case writing your own decorator is easy enough.


>
>>
>> On Thu, Jan 23, 2014 at 10:31 AM, Suresh V.
>> <suresh_vv at yahoo.com
>> <mailto:suresh_vv at yahoo.com>> wrote:
>>
>>     Nicely done :-)
>>
>>     "foo" may come from a library or something, so rather than a
>>     decorator we may have to monkey patch it. Unless there is a nicer
>>     solution.
>>
>>     Will functools be a good place for something like this?
>>
>>
>>     On Thursday 23 January 2014 01:50 PM, Chris Angelico wrote:
>>
>>         On Thu, Jan 23, 2014 at 7:11 PM, Suresh V.
>>         <suresh_vv at yahoo.com
>>         <mailto:suresh_vv at yahoo.com>> wrote:
>>
>>             On Thursday 23 January 2014 01:22 PM, Chris Angelico wrote:
>>
>>
>>                 On Thu, Jan 23, 2014 at 6:20 PM, Suresh V.
>>                 <suresh_vv at yahoo.com
>>                 <mailto:suresh_vv at yahoo.com>> wrote:
>>
>>
>>                     Can we add these two attributes for every
>>                     function/method where each is a
>>                     list of callables with the same arguments as the
>>                     function/method itself?
>>
>>                     Pardon me if this has been discussed before.
>>                     Pointers to past discussions
>>                     (if any) appreciated.
>>
>>
>>
>>                 I'm not exactly sure what you're looking for here. What
>>                 causes a
>>                 callable to be added to a function's __before__ list,
>>                 and/or what will
>>                 be done with it?
>>
>>
>>
>>             These are modifiable attributes, so something can be
>>             added/deleted from the
>>             __before__ or __after__ lists.
>>
>>
>>
>>                 If you mean that they'll be called before and after the
>>                 function
>>                 itself, that can be more cleanly done with a decorator.
>>
>>
>>
>>             Yes. Each item in the list will be called in order
>>             immediately before/after
>>             each invocation of the function. This is kinda like
>>             decorators, but more
>>             flexible and simpler. Scope for abuse may be higher too :-)
>>
>>
>>         def prepostcall(func):
>>               def wrapper(*args,**kwargs):
>>                   for f in wrapper.before: f(*args,**kwargs)
>>                   ret = func(*args,**kwargs)
>>                   for f in wrapper.after: f(*args,**kwargs)
>>                   return ret
>>               wrapper.before = []
>>               wrapper.after = []
>>               return wrapper
>>
>>         @prepostcall
>>         def foo(x,y,z):
>>               return x*y+z
>>
>>         foo.before.append(lambda x,y,z: print("Pre-call"))
>>         foo.after.append(lambda x,y,z: print("Post-call"))
>>
>>         Now just deal with the question of whether the after functions
>>         should
>>         be called if the wrapped function throws :)
>>
>>
>>
>>
>>
>>         ChrisA
>>         _________________________________________________
>>         Python-ideas mailing list
>>         Python-ideas at python.org
>>         <mailto:Python-ideas at python.org>
>>         https://mail.python.org/__mailman/listinfo/python-ideas
>>         <https://mail.python.org/mailman/listinfo/python-ideas>
>>         Code of Conduct: http://python.org/psf/__codeofconduct/
>>         <http://python.org/psf/codeofconduct/>
>>
>>
>>
>>     _________________________________________________
>>     Python-ideas mailing list
>>     Python-ideas at python.org
>>     <mailto:Python-ideas at python.org>
>>     https://mail.python.org/__mailman/listinfo/python-ideas
>>     <https://mail.python.org/mailman/listinfo/python-ideas>
>>     Code of Conduct: http://python.org/psf/__codeofconduct/
>>
>>     <http://python.org/psf/codeofconduct/>
>>
>>
>>
>>
>> _______________________________________________
>> Python-ideas mailing list
>> Python-ideas at python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>>
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20140123/43f1f16d/attachment.html>


More information about the Python-ideas mailing list