[Python-ideas] Before and after the colon in funciton defs.
MRAB
python at mrabarnett.plus.com
Wed Sep 21 21:30:41 CEST 2011
On 21/09/2011 19:34, Guido van Rossum wrote:
> When you say "compile time", do you literally mean "when the compiler
> creates the bytecode" or do you really intend this to be computed at
> function definition time (the same time when default values are
> evaluated)? The latter seems to make more sense.
>
It would be at function definition time.
> --Guido
>
> On Wed, Sep 21, 2011 at 11:12 AM, Ron Adam<ron3200 at gmail.com> wrote:
>> On Wed, 2011-09-21 at 15:19 +1000, Nick Coghlan wrote:
>>
>>> 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
>>
>> Simplifying things like this is one of the use cases of allowing define
>> time statements. That's a lot of work to just avoid putting a keyword
>> in the signature. And it's not easy to understand.
>>
>> Decorators could be a good way to do this, but the problem in these
>> cases, is the function object doesn't have the needed support to make
>> things like this easy.
>>
>>
>> Probably the easiest and most direct way, would to be to add a new
>> keyword 'static' as MRAB suggested, but have it be an expression instead
>> of a command.
>>
>> value = (static<expression>)
>>
>>
>> def adder(x):
>> return x + (static i) # evaluate (static i) at compile time.
>>
>> The parentheses would be optional.
>>
>> The (static i) expression, could be spelled (i=i). I think that was
>> what Guido was suggesting, but not as an expression. As an expression,
>> you would then see things like.. i = (i=i). But that may only be poor
>> style, because it's easy enough to just not do that.
>>
>> I think the expression form is better myself, it allows you to get both
>> the compile time value, and the current value of an identifier.
>>
>>
>> def value elapsed_frames():
>> """ Where f is the frame counter in the parent scope. """
>> return f - (static f)
>>
A function to calculate a Fibonacci number with memoisation would
change from:
def fib(n, known={}):
if n in known:
return known[n]
if n < 2:
f = n
else:
f = fib(n - 1) + fib(n - 2)
known[n] = f
return f
to:
def fib(n):
known = static {}
if n in known:
return known[n]
if n < 2:
f = n
else:
f = fib(n - 1) + fib(n - 2)
known[n] = f
return f
This:
known = {}
creates a dict and binds a name to it at execution time, whereas
this:
known = static {}
creates a dict at definition time, storing a reference to it in the
function object, and binds a name to it at execution time.
I suppose it's like a class variable:
class Foo:
known = {}
which is shared by its instances.
More information about the Python-ideas
mailing list