Path: csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!feeder.erje.net!eu.feeder.erje.net!newsfeed.freenet.ag!news2.euro.net!newsgate.cistron.nl!newsgate.news.xs4all.nl!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; 'else:': 0.03; 'args': 0.04; 'attribute': 0.05; 'context': 0.05; 'sys': 0.05; '*args,': 0.07; 'arguments': 0.07; 'function,': 0.07; 'method,': 0.07; 'parameter': 0.07; 'subject:code': 0.07; '**kwargs)': 0.09; '**kwargs):': 0.09; '*name*': 0.09; '8bit%:2': 0.09; 'accepts': 0.09; 'argument,': 0.09; 'broken.': 0.09; 'kwargs': 0.09; 'cc:addr :python-list': 0.10; 'def': 0.10; 'itself.': 0.11; '(args': 0.16; 'argument.': 0.16; 'attrs': 0.16; 'both.': 0.16; 'broken,': 0.16; 'dict(': 0.16; 'help?': 0.16; 'here.\xa0': 0.16; 'renames': 0.16; 'skip:@ 20': 0.16; 'to:addr:pearwood.info': 0.16; 'to:addr:steve+comp.lang.python': 0.16; "to:name:steven d'aprano": 0.16; 'mon,': 0.16; 'wrote:': 0.17; '8bit%:3': 0.17; 'jan': 0.18; 'appears': 0.18; 'code.': 0.20; 'trying': 0.21; 'import': 0.21; 'thanks.': 0.21; '\xa0if': 0.22; 'cc:2**0': 0.23; '>': 0.23; 'this:': 0.23; 'seems': 0.23; 'cc:addr:python.org': 0.25; 'header :In-Reply-To:1': 0.25; 'looks': 0.26; 'skip:m 30': 0.26; 'message- id:@mail.gmail.com': 0.27; 'context,': 0.29; "d'aprano": 0.29; 'steven': 0.29; 'url:mailman': 0.29; '8bit%:5': 0.29; 'skip:_ 10': 0.29; 'skip:& 10': 0.29; 'probably': 0.29; 'class': 0.29; "i'm": 0.29; 'maybe': 0.29; 'function': 0.30; 'url:python': 0.32; 'skip:_ 30': 0.32; 'url:listinfo': 0.32; 'builds': 0.33; 'skip:& 20': 0.33; 'received:google.com': 0.34; 'thanks': 0.34; 'whatever': 0.35; 'so,': 0.35; 'pm,': 0.35; 'received:209.85.220': 0.35; 'received:209.85': 0.35; 'something': 0.35; 'skip:_ 40': 0.35; 'except': 0.36; 'explain': 0.36; 'url:org': 0.36; 'skip:m 40': 0.36; 'method': 0.36; 'author': 0.37; 'does': 0.37; 'passed': 0.37; 'received:209': 0.37; 'subject:: ': 0.38; 'skip:" 10': 0.40; 'header:Received:5': 0.40; 'url:mail': 0.40; 'here': 0.65; 'brown': 0.65; '2013': 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 :cc:content-type; bh=YzV6M12D5PhQ4Dz74huMtwpWx1g/b++i8urBCeo3WIs=; b=wBjhV8LlNoaIPdaVDKm5U38BGXvrOGuuxa0GSF7gOe8O+yHzTCwx8Pvy4ric6k5O7X io8Em0cEaYyb3dBCRtIozp/aedfs2Cze4hH9igRVdVhRGLBxYWDjNPUdedyztViL0vGT r3AInHT3IiE/m7X9Iw9zn7p3xdrK+UwxobVhKVdlZ271MXV8Or3Shm0bQBv4uBgAPf9a ykiG/eMSsAuNqVP4OdEP4V/0JFEsVF/D4w8kjSW127ulA8f6V5RwIZce4NDWpaNi1PgN BIwmy8eTCSYzl4SOPqLV9rnlGynMKHQoPUI7YheyiEqpxBwGHli9eccAmn7U7Rc0qAxb kIAA== MIME-Version: 1.0 In-Reply-To: <50f4dd31$0$29983$c3e8da3$5496439d@news.astraweb.com> References: <50f4dd31$0$29983$c3e8da3$5496439d@news.astraweb.com> From: Rodrick Brown Date: Mon, 14 Jan 2013 23:51:40 -0500 Subject: Re: code explanation To: "Steven D'Aprano" Content-Type: multipart/alternative; boundary=bcaec543094c3e6e9a04d34c860c Cc: "python-list@python.org" 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: 261 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1358225540 news.xs4all.nl 6894 [2001:888:2000:d::a6]:47230 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:36835 --bcaec543094c3e6e9a04d34c860c Content-Type: text/plain; charset=ISO-8859-1 On Mon, Jan 14, 2013 at 11:38 PM, Steven D'Aprano < steve+comp.lang.python@pearwood.info> wrote: > On Mon, 14 Jan 2013 23:00:16 -0500, Rodrick Brown wrote: > > > Can someone explain what's going on here. > > > > def _build_magic_dispatcher(method): > > def inner(self, *args, **kwargs): > > return self.__dict__[method](*args, **kwargs) > > inner.__name__ = method > > return inner > > > > Thanks. > > > This is a factory function, probably intended to be used as a decorator: > > class K: > @_build_magic_dispatcher > def something(self, x, y, z): ... > > except that it appears to be broken. It seems to be expecting a *string*, > the name of a method, despite the function parameter claiming to require > a method itself. So maybe you use it like this: > > class K: > def __init__(self): > self.parrot = _build_magic_dispatcher("parrot") > > > or something similar. Without seeing the context, it's hard for me to > tell whether it works or is broken. I suspect it is broken, or useless, > or both. > > So, this factory function seems to take the *name* of a method as > argument. Then it builds an inner method, which accepts arbitrary > arguments (args and kwargs), renames the inner method to the name you > passed as argument, and returns it. > > Thanks Steven, here is the full context of the code. I'm trying to understand what exactly the author is trying to accomplish here. import sys PY3K = sys.version_info >= (3,) methods = set([ "__iter__", "__len__", "__contains__", "__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__", "__add__", "__and__", "__divmod__", "__floordiv__", "__lshift__", "__mod__", "__mul__", "__or__", "__pow__", "__rshift__", "__sub__", "__truediv__", "__xor__", ]) if PY3K: methods.add("__next__") methods.add("__bool__") else: methods.add("__div__") methods.add("__nonzero__") MAGIC_METHODS = frozenset(methods) del methods def _build_magic_dispatcher(method): def inner(self, *args, **kwargs): return self.__dict__[method](*args, **kwargs) inner.__name__ = method return inner class stub(object): _classes_cache = {} def __new__(cls, **kwargs): magic_methods_present = MAGIC_METHODS.intersection(kwargs) if magic_methods_present not in cls._classes_cache: attrs = dict( (method, _build_magic_dispatcher(method)) for method in magic_methods_present ) attrs["__module__"] = cls.__module__ cls._classes_cache[magic_methods_present] = type("stub", (cls,), attrs) new_cls = cls._classes_cache[magic_methods_present] return super(stub, new_cls).__new__(new_cls, **kwargs) def __init__(self, **kwargs): self.__dict__.update(kwargs) > The inner method simply looks up an attribute with the same name, and > calls it as a function with whatever args and kwargs it gets. > > > Does this help? > > > > -- > Steven > -- > http://mail.python.org/mailman/listinfo/python-list > --bcaec543094c3e6e9a04d34c860c Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
On Mon, Jan 14, 2013 at 11:38 P= M, Steven D'Aprano <steve+comp.lang.python@pearwood= .info> wrote:
On Mon, 14 Jan 2013 23:00:16 -0500, Rodrick Brown wrote:

> Can someone explain what's going on here.
>
> def _build_magic_dispatcher(method):
> =A0 =A0 def inner(self, *args, **kwargs):
> =A0 =A0 =A0 =A0 return self.__dict__[method](*args, **kwargs)
> =A0 =A0 inner.__name__ =3D method
> =A0 =A0 return inner
>
> Thanks.


This is a factory function, probably intended to be used as a d= ecorator:

class K:
=A0 =A0 @_build_magic_dispatcher
=A0 =A0 def something(self, x, y, z): ...

except that it appears to be broken. It seems to be expecting a *string*, the name of a method, despite the function parameter claiming to require a method itself. So maybe you use it like this:

class K:
=A0 =A0 def __init__(self):
=A0 =A0 =A0 =A0 self.parrot =3D _build_magic_dispatcher("parrot")=


or something similar. Without seeing the context, it's hard for me to tell whether it works or is broken. I suspect it is broken, or useless,
or both.

So, this factory function seems to take the *name* of a method as
argument. Then it builds an inner method, which accepts arbitrary
arguments (args and kwargs), renames the inner method to the name you
passed as argument, and returns it.


Thanks Steven, here is the full = context of the code. I'm trying to understand what exactly the author i= s trying to accomplish here.=A0

import sys

PY3K =3D sys.version_info >=3D (3,)


methods =3D set([
=A0 =A0 "__iter__&= quot;,
=A0 =A0 "__len__",
=A0 =A0 "__con= tains__",

=A0 =A0 "__lt__",
=A0 =A0 "__l= e__",
=A0 =A0 "__eq__",
=A0 =A0 "__= ne__",
=A0 =A0 "__gt__",
=A0 =A0 "_= _ge__",

=A0 =A0 "__add__",
=A0 =A0 "__and__= ",
=A0 =A0 "__divmod__",
=A0 =A0 "_= _floordiv__",
=A0 =A0 "__lshift__",
=A0 = =A0 "__mod__",
=A0 =A0 "__mul__",
=A0 =A0 "__or__",
=A0 =A0 "__pow__",
=A0 =A0 "__rshift__"= ;,
=A0 =A0 "__sub__",
=A0 =A0 "__truediv= __",
=A0 =A0 "__xor__",
]) =A0 =A0 =A0
if PY3K: = =A0 =A0
=A0 =A0 methods.add("__next__")
=A0 = =A0 methods.add("__bool__")
else: =A0 =A0 =A0=A0
<= div>=A0 =A0 methods.add("__div__")
=A0 =A0 methods.add("__nonzero__")
MAGIC_METHODS = =3D frozenset(methods)
del methods

def _build_magic_dispatcher(method):
=A0 =A0 def inner(self= , *args, **kwargs):
=A0 =A0 =A0 =A0 return self.__dict__[method](*args, **kwargs)
=A0 =A0 inner.__name__ =3D method
=A0 =A0 return inner


class stub(object):
=A0 =A0 _clas= ses_cache =3D {}

=A0 =A0 def __new__(cls, **kwargs):
=A0 =A0 = =A0 =A0 magic_methods_present =3D MAGIC_METHODS.intersection(kwargs)
<= div>=A0 =A0 =A0 =A0 if magic_methods_present not in cls._classes_cache:
=A0 =A0 =A0 =A0 =A0 =A0 attrs =3D dict(
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (method, _build_magic_dispatcher(metho= d))
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 for method in magic_methods_p= resent
=A0 =A0 =A0 =A0 =A0 =A0 )
=A0 =A0 =A0 =A0 =A0 = =A0 attrs["__module__"] =3D cls.__module__
=A0 =A0 =A0 =A0 =A0 =A0 cls._classes_cache[magic_methods_present] =3D = type("stub", (cls,), attrs)
=A0 =A0 =A0 =A0 new_cls =3D= cls._classes_cache[magic_methods_present]
=A0 =A0 =A0 =A0 return= super(stub, new_cls).__new__(new_cls, **kwargs)

=A0 =A0 def __init__(self, **kwargs):
=A0 =A0= =A0 =A0 self.__dict__.update(kwargs)
=A0
The inner method simply looks up an attribute with the same name, and
calls it as a function with whatever args and kwargs it gets.


Does this help?



--
Steven
--
http://mail.python.org/mailman/listinfo/python-list

--bcaec543094c3e6e9a04d34c860c--