[Python-ideas] Before and after the colon in funciton defs.

Nick Coghlan ncoghlan at gmail.com
Wed Sep 21 07:19:18 CEST 2011


On Wed, Sep 21, 2011 at 1:36 PM, Terry Reedy <tjreedy at udel.edu> wrote:
> On 9/20/2011 1:09 PM, Guido van Rossum wrote:
>> I would be much more interested in a tweak to the language semantics
>> where the compiler is allowed to assume that "len means len" if there
>> is no global assignment to it in a module. There are many past threads
>> about this topic. It should make the feature proposed here unnecessary
>> -- at least its use for manual micro-optimizations, which I mostly
>> find an offense to the reader (even in the shortened form proposed
>> here).
>
> For those not party to the earlier threads, this alternate proposal would
> bread any code that monkeypatches an imported-module-only override of a
> builtin, something like:
>
> def mylen(o): return <whatever>
> import mod; mod.len = mylen
>
> I do not mind the semantic change itself, and it would benefit nearly all
> code, including module-level code would not be affected by def gimmicks.
> Some issues I see that perhaps were discussed, but I do not remember: 1)
> module.__setattr__ should then raise an exception at such attempts; 2) it
> makes the language more context sensitive than it currently is; 3) compile()
> should apply the rule even for single statements or even expressions.

The two sticking points tend to be open() and print(). Overriding
those externally can be *incredibly* useful for testing code that uses
them, as well as in interacting with code that wasn't designed in a
flexible way.

Regardless, I'm going to stop mentioning the manual micro-optimisation
use case for the default argument hack. Alex Gaynor pointed out that
that aspect is completely irrelevant on PyPy, and as Guido notes,
there are likely other ways to tackle name lookup optimisation even in
CPython.

That still leaves two arguably valid use cases:

- early binding for name lookups
- an algorithm with shared state (kind of like an inverted approach to
creating a class with a custom __call__ method)

Perhaps a non-syntax way to approach both of these would be to add a
new decorator to 'functools':

    def closure(f):
        """Invokes the decorated function and returns the result after
transcribing essential function metadata

           This can be used to easily share algorithm state and get
early binding semantics for names.
        """
        impl = f()
        impl.__name__ = f.__name__
        doc = f.__doc__
        if doc is not None:
            impl.__doc__ = doc
        impl.__dict__.update(f.__dict__)
        return impl

This would be used as follows:

    @functools.closure
    def adder(i=i): # 'impl' defines call time signature
        "Increments 'x' by adder.value"
        def impl(x):
            impl.call_count += 1
            return x + i
        impl.value = i
        impl.call_count = 0
        return impl

>>> adder.value
10
>>> adder(1)
11
>>> adder(5)
15
>>> adder(10)
20
>>> adder.call_count
3

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia



More information about the Python-ideas mailing list