On Mon, May 20, 2013 at 7:54 PM, Cameron Simpson <c...@zip.com.au> wrote: > On 20May2013 19:09, Chris Angelico <ros...@gmail.com> wrote: > | On Mon, May 20, 2013 at 6:35 PM, Cameron Simpson <c...@zip.com.au> wrote: > | > _lock = Lock() > | > > | > def lprint(*a, **kw): > | > global _lock > | > with _lock: > | > print(*a, **kw) > | > > | > and use lprint() everywhere? > | > | Fun little hack: > | > | def print(*args,print=print,lock=Lock(),**kwargs): > | with lock: > | print(*args,**kwargs) > | > | Question: Is this a cool use or a horrible abuse of the scoping rules? > > I carefully avoided monkey patching print itself:-) > > That's... mad! I can see what the end result is meant to be, but > it looks like a debugging nightmare. Certainly my scoping-fu is too > weak to see at a glance how it works.
Hehe. Like I said, could easily be called abuse. Referencing a function's own name in a default has to have one of these interpretations: 1) It's a self-reference, which can be used to guarantee recursion even if the name is rebound 2) It references whatever previously held that name before this def statement. Either would be useful. Python happens to follow #2; though I can't point to any piece of specification that mandates that, so all I can really say is that CPython 3.3 appears to follow #2. But both interpretations make sense, and both would be of use, and use of either could be called abusive of the rules. Figure that out. :) The second defaulted argument (lock=Lock()), of course, is a common idiom. No abuse there, that's pretty Pythonic. This same sort of code could be done as a decorator: def serialize(fn): lock=Lock() def locked(*args,**kw): with lock: fn(*args,**kw) return locked print=serialize(print) Spelled like this, it's obvious that the argument to serialize has to be the previous 'print'. The other notation achieves the same thing, just in a quirkier way :) ChrisA -- http://mail.python.org/mailman/listinfo/python-list