List of Functions

Chris Angelico rosuav at gmail.com
Tue Mar 29 01:00:06 EDT 2016


On Tue, Mar 29, 2016 at 3:45 PM, Marko Rauhamaa <marko at pacujo.net> wrote:
> Chris Angelico <rosuav at gmail.com>:
>
>> On Tue, Mar 29, 2016 at 12:40 AM, Marko Rauhamaa <marko at pacujo.net> wrote:
>>> Dan Sommers <dan at tombstonezero.net>:
>>>
>>>> On Mon, 28 Mar 2016 11:58:54 +0300, Marko Rauhamaa wrote:
>>>>
>>>>> As for Python, I don't feel a great need for anonymous functions.
>>>>> However, I keep running into a need for anonymous classes, or,
>>>>> rather, classless objects. Not a biggie. I just create a one-off
>>>>> inner class and instantiate it, but I do appreciate Java's syntactic
>>>>> innovation.
>>>>
>>>> And I always curse Java for having to create an inner class and a
>>>> method when all I need is a simple function. :-)
>>>>
>>>> I think it's Steven D'Aprano who keeps pointing out that you can
>>>> always name your tiny helper functions instead of using lambda:
>>>>
>>>>     def some_complex_function():
>>>>         def f(x) = x + 2
>>>>         some_library_that_wants_a_callback(f)
>>>>         some_library_that_wants_a_callback(lambda x: x + 2)
>>>>
>>>> Both calls to some_library_that_wants_a_callback run the same.
>>>
>>> Yes, but I've come to realize that I quite often need more than a
>>> function: I need an object with behavior. The solution is to use a
>>> "helper" class.
>>
>> Can you give an example of code that would benefit from a
>> "lambda-class" construct?
>
> Here's a recent example:
>
> ========================================================================
>             def process(self, source):
>                 awk = self
>                 class Source(snake.FieldSource):
>                     def emit_fields(self):
>                         for fields in snake.get_fields(
>                                 source, awk.encoding, awk.errors,
>                                 awk.eol, awk.delim):
>                             if awk.selector is None or awk.selector(fields):
>                                 yield [ fields[i] for i in awk.columns ]
>                 return Source(self.encoding, self.errors, self.eol, self.delim)
> ========================================================================
>
> Here's another, older one:
>
> ========================================================================
>     def __init__(self, server, sock, domain, peer):
>         super().__init__(server, sock)
>         conn = self
>         client_ip = peer[0]
>
>         [...]
>
>         class SPF_HELO(STATE):
>             def terminate(self):
>                 conn.resume()
>                 conn.spf_query.cancel()
>                 conn.close()
>                 if conn.timer is not None:
>                     conn.timer.cancel()
>                     conn.timer = None
>                 conn.set_state(ZOMBIE)
>
>             def handle_spf_verdict(self, verdict, reason, *capabilities):
>                 conn.resume()
>                 conn.log("verdict {} reason {}".format(verdict, reason))
>                 # RFC 4408 §2.5.5 calls for leniency for SoftFail
>                 #if verdict in [ SPFClient.FAIL, SPFClient.SOFT_FAIL ]:
>                 if verdict in [ SPFClient.FAIL ]:
>                     conn.respond(550, "SPF check failed: {}".format(reason))
>                     conn.set_state(IDLE)
>                     return
>                 conn.respond(250, server.domain, *capabilities)
>                 conn.set_state(IDLE)
> ========================================================================

Since those functions have statements in them, there's not going to be
any way to construct this class as an expression (short of stupid
messing around with exec, which would be a bad idea). So the best
you're likely to be able to do is a metaclass or decorator that
short-hands the instantiation - or crafting your other code such that
it takes the class, rather than an instance of the class. The latter
is quite Pythonic, but generally not as well regarded in other
languages, sometimes for obvious reasons like "classes aren't first
class objects". :)

ChrisA



More information about the Python-list mailing list