Path: csiph.com!usenet.pasdenom.info!news.redatomik.org!newsfeed.xs4all.nl!newsfeed3.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.002 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'defaults': 0.07; 'arguments': 0.09; 'decorator': 0.09; 'function:': 0.09; 'spec': 0.09; 'wrapped': 0.09; 'python': 0.11; 'def': 0.12; 'suggest': 0.14; '**kwargs)': 0.16; '**kwargs):': 0.16; 'binding,': 0.16; 'binding.': 0.16; 'inconvenient': 0.16; 'readable': 0.16; 'skip:@ 20': 0.16; 'subject:parameters': 0.16; 'supplied,': 0.16; 'wraps': 0.16; 'language': 0.16; 'wrote:': 0.18; 'import': 0.22; 'purposes': 0.26; 'values': 0.27; 'header:In-Reply-To:1': 0.27; 'function': 0.29; 'michael': 0.29; 'am,': 0.29; 'message- id:@mail.gmail.com': 0.30; 'code': 0.31; 'usually': 0.31; "d'aprano": 0.31; 'inspect': 0.31; 'relies': 0.31; 'steven': 0.31; 'writes:': 0.31; 'run': 0.32; 'fri,': 0.33; 'actual': 0.34; 'could': 0.34; "can't": 0.35; 'late': 0.35; 'but': 0.35; 'received:google.com': 0.35; 'to:addr:python-list': 0.38; 'to:addr:python.org': 0.39; 'tell': 0.60; 'simple': 0.61; 'name': 0.63; 'provide': 0.64; 'default': 0.69; 'evaluate': 0.72; '2015': 0.84; 'welle': 0.84 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :content-type; bh=2Ns10RTtA81QHut4MePLM+8Kve7311QuChGTTbS3RRA=; b=NVkS+oqddXFf9VB++fRyOnnODAYBW0iQLkc6EMxLvQr2bd9oR/bRjv5UJDPNryL4vO Vsii0HU+btuoYDND9DHho32dKTTcQjJshpti7ojUgGOgpfC1h4GVrBfrd17QCIys9l6Z bWAMIG+/Z6cglUQAuDP6WtobD1iyOUcDAwQT9fUKyjlcoPRBuq+mnZKdGWkYc0Acqp8O rKc8ZnwLPkPiOfzk8lunQ9C5cguWq6/ddm8WuVd1rkkFBSrJzeznaInqqdiKfMxn9fs7 AIPFLsgBR4EmCn++F+RZhEaXNNepTnyulIV+ogu2GYvLl8uHgVP7kze2FtVFX8YIcjoI wjsw== X-Received: by 10.43.65.19 with SMTP id xk19mr3729480icb.20.1431190661691; Sat, 09 May 2015 09:57:41 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: References: <72lu1cxvmg.ln2@news.c0t0d0s0.de> <554cd511$0$12979$c3e8da3$5496439d@news.astraweb.com> From: Ian Kelly Date: Sat, 9 May 2015 10:57:01 -0600 Subject: Re: functions, optional parameters To: Python Content-Type: text/plain; charset=UTF-8 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 57 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1431190664 news.xs4all.nl 2930 [2001:888:2000:d::a6]:50659 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:90241 On Fri, May 8, 2015 at 9:50 AM, Michael Welle wrote: > > Steven D'Aprano writes: >> >> If your language uses late binding, it is very inconvenient to get early >> binding when you want it. But if your language uses early binding, it is >> very simple to get late binding when you want it: just put the code you >> want to run inside the body of the function: > And you have to do it all the time again and again. I can't provide hard > numbers, but I think usually I want late binding. You could perhaps write a decorator to evaluate your defaults at call time. This one relies on inspect.signature, so it requires Python 3.3 or newer: import inspect from functools import wraps def late_defaults(**defaults): def decorator(f): sig = inspect.signature(f) @wraps(f) def wrapped(*args, **kwargs): bound_args = sig.bind_partial(*args, **kwargs) for name, get_value in defaults.items(): if name not in bound_args.arguments: bound_args.arguments[name] = get_value() return f(*bound_args.args, **bound_args.kwargs) return wrapped return decorator @late_defaults(b=lambda: x+1, c=lambda: y*2) def f(a, b, c=None): print(a, b, c) x = 14 y = 37 f(10) x = 30 y = 19 f(10) f(10, 11) f(10, 11, c=12) Output: 10 15 74 10 31 38 10 11 38 10 11 12 For documentation purposes I suggest using default values of None in the function spec to indicate that the arguments are optional, and elaborating on the actual defaults in the docstring. Alternatively you could put the lambdas in the the actual function spec and then just tell the decorator which ones to apply if not supplied, but that would result in less readable pydoc.