Path: csiph.com!usenet.pasdenom.info!gegeweb.org!de-l.enfer-du-nord.net!feeder1.enfer-du-nord.net!feeds.phibee-telecom.net!newsfeed.xs4all.nl!newsfeed5.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.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'syntax': 0.03; 'essentially': 0.04; 'method.': 0.05; 'decorator': 0.07; 'nested': 0.07; 'wrapped': 0.07; 'wrapper': 0.07; 'accepts': 0.09; 'ignoring': 0.09; 'maker': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'sep': 0.09; 'terry': 0.09; 'def': 0.10; 'subject:not': 0.11; 'passing': 0.15; '**kwds)': 0.16; '**kwds):': 0.16; 'nesting': 0.16; 'received:80.91.229.3': 0.16; 'received:plane.gmane.org': 0.16; 'reedy': 0.16; 'simpler,': 0.16; 'simpson': 0.16; 'wrote:': 0.17; 'jan': 0.18; 'define': 0.20; 'parameters': 0.20; 'people,': 0.21; 'effort.': 0.22; 'explicit': 0.22; 'least': 0.25; 'header:In-Reply-To:1': 0.25; 'header:User- Agent:1': 0.26; 'am,': 0.27; 'skip:@ 10': 0.27; 'header:X -Complaints-To:1': 0.28; 'words': 0.29; 'class': 0.29; "i'm": 0.29; 'call.': 0.30; 'function': 0.30; 'code': 0.31; 'to:addr :python-list': 0.33; 'compared': 0.35; 'pm,': 0.35; 'there': 0.35; 'received:org': 0.36; 'but': 0.36; 'does': 0.37; 'option': 0.37; 'level': 0.37; 'subject:: ': 0.38; 'some': 0.38; 'to:addr:python.org': 0.39; 'header:Received:5': 0.40; 'think': 0.40; 'skip:u 10': 0.60; 'most': 0.61; 'first': 0.61; 'worth': 0.63; 'here': 0.65; 'burden': 0.65; 'difficulty': 0.65; 'below.': 0.68; 'gain': 0.79; 'cognitive': 0.84; 'irrelevant': 0.84; 'pain': 0.84; 'received:fios.verizon.net': 0.84; 'wrapper,': 0.84 X-Injected-Via-Gmane: http://gmane.org/ To: python-list@python.org From: Terry Reedy Subject: Re: Decorators not worth the effort Date: Fri, 14 Sep 2012 16:29:25 -0400 References: <20120914021211.GA15642@cskk.homeip.net> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Gmane-NNTP-Posting-Host: pool-173-75-251-66.phlapa.fios.verizon.net User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20120824 Thunderbird/15.0 In-Reply-To: <20120914021211.GA15642@cskk.homeip.net> X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 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: 64 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1347654606 news.xs4all.nl 6986 [2001:888:2000:d::a6]:51382 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:29184 On 9/13/2012 10:12 PM, Cameron Simpson wrote: > On 13Sep2012 18:58, alex23 wrote: > | On Sep 14, 3:54 am, Jean-Michel Pichavant > | wrote: > | > I don't like decorators, I think they're not worth the mental effort. > | > | Because passing a function to a function is a huge cognitive burden? For parameterized decorators, there is extra cognitive burden. See below. > It is for me when I'm _writing_ the decorator:-) But if I get it right > and name it well I find it dramaticly _decreases_ the cognitive burden > of the code using the decorator... For a simple, unparameterized wrapper, the difficulty is entirely in the wrapper maker. It must define the final wrapper as a nested function and return it*. It is irrelevant whether the wrapper maker is used with pre-def decorator syntax or with an explicit post-def call. *I am here ignoring the option of a class with __call__ method. For a parameterized wrapper, using decorator syntax requires passing the parameter(s) first and the function to be wrapped later. This requires currying the wrapper maker with double nesting. The nesting order may seem inside-out to some. For most people, this is extra work compared to writing a wrapper that accepts the function and parameters together and only has a single level of nesting. In other words def make_wrapper(func, param): def wrapper(*args, **kwds): for i in range(param): func(*args, **kwds) return wrapper def f(x): print(x) f = make_wrapper(f, 2) f('simple') # is simpler, at least for some people, than the following # which does essentially the same thing. def make_outer(param): def make_inner(func): def wrapper(*args, **kwds): for i in range(param): func(*args, **kwds) return wrapper return make_inner @make_outer(2) def f(x): print(x) f('complex') Is the gain of not repeating the wrapped function name twice in the post-def wrapping call, and the gain of knowing the function will be wrapped before reading the def, worth the pain of currying the wrapper maker? -- Terry Jan Reedy