Welcome, guest | Sign In | My Account | Store | Cart

Python default values for keyword arguments are evaluated only once and not on every function call. For example following function will not work as user may expect:

def printNow(l=[], now=datetime.now()):
    l.append(len(l))

    print('List:', l, ' id:', id(l))
    print('Now:', now)


for i in range(3):
    printNow()
    print()

The "dynamic" decorator solves problem by evaluating callables, that are assigned to parameters using annotations syntax (see PEP 3107).

Python, 30 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from datetime import datetime
from functools import wraps

def dynamic(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
        for key, value in fn.__annotations__.items():
            try:
                kwargs[key] = value()
            except TypeError:
                pass
            
        return fn(*args, **kwargs)
    return wrapper


# Example

@dynamic
def printNow(l:list, now:datetime.now):
    l.append(len(l))
    
    print('List:', l, ' id:', id(l))
    print('Now:', now)
    
# Test

for i in range(3):
    printNow()
    print()
Created by pavel on Wed, 22 Feb 2012 (MIT)
Python recipes (4591)
pavel's recipes (5)

Required Modules

  • (none specified)

Other Information and Tasks