[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