Path: csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!news.albasani.net!rt.uk.eu.org!newsfeed.xs4all.nl!newsfeed1.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; 'attribute': 0.07; 'lines,': 0.07; 'currently,': 0.09; 'instances.': 0.09; 'lookup': 0.09; 'method,': 0.09; 'modulo': 0.09; 'obj': 0.09; 'pep': 0.09; 'propagate': 0.09; 'subject:Function': 0.09; 'try:': 0.09; 'cc:addr:python-list': 0.11; 'python': 0.11; 'def': 0.12; 'attribute,': 0.16; 'change;': 0.16; 'define:': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'func': 0.16; 'globals': 0.16; 'globals.': 0.16; 'heap': 0.16; 'item):': 0.16; 'kw:': 0.16; 'letting': 0.16; 'surprising': 0.16; 'think.': 0.16; 'exception': 0.16; 'wrote:': 0.18; 'bit': 0.19; 'first.': 0.19; 'possible,': 0.19; 'written,': 0.19; 'import': 0.22; 'cc:addr:python.org': 0.22; 'module,': 0.24; 'visible': 0.24; 'mon,': 0.24; 'cc:2**0': 0.24; 'equivalent': 0.26; 'this:': 0.26; 'pass': 0.26; 'post': 0.26; 'defined': 0.27; 'header:In- Reply-To:1': 0.27; 'function': 0.29; '[1]': 0.29; 'am,': 0.29; 'raise': 0.29; "doesn't": 0.30; 'message-id:@mail.gmail.com': 0.30; 'along': 0.30; 'work.': 0.31; '(which': 0.31; 'equivalent.': 0.31; 'class': 0.32; 'another': 0.32; 'quite': 0.32; 'becomes': 0.33; 'actual': 0.34; 'trouble': 0.34; 'sense': 0.34; 'skip:_ 10': 0.34; 'could': 0.34; 'problem': 0.35; 'subject: (': 0.35; 'except': 0.35; 'problem.': 0.35; 'case,': 0.35; 'but': 0.35; 'received:google.com': 0.35; 'there': 0.35; 'doing': 0.36; 'possible': 0.36; 'two': 0.37; 'e.g.': 0.38; 'question,': 0.38; 'whatever': 0.38; 'that,': 0.38; 'does': 0.39; 'extremely': 0.39; 'even': 0.60; 'around.': 0.60; 'matter': 0.61; 'first': 0.61; 'back': 0.62; 'become': 0.64; 'more': 0.64; 'different': 0.65; 'circle': 0.68; 'fact,': 0.69; 'evaluate': 0.72; 'special': 0.74; 'effects,': 0.84; 'off,': 0.84; 'usage.': 0.84; 'to:none': 0.92 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:cc :content-type; bh=xElvIbZqp1ELY5YU6vYYlEB4ldGWCmtHlHDDGMOCTJE=; b=Nz2hwBSo4KGiAUjSrctupNP9OHXlRJDLpKQUQ0+yVyyVL3qiIB2lgdq7LbVhLXgB2h QLN4JZIEFQsH5gG/Rgz0CgUTp8FnYAKMijyhbOb1hNvG/tvoFnwqDRO8YTS1Ol16Dt/G L2OlrCP+uqmFh0uCxtBlwsCxr3SAOfG1rcD5w/HOQ76tTy08egA57Njh+94J93YN7hlj 3Z+oblmCo3Zj4UN+a6ZYNNr7sgN2bZfmO5GNqkL1f9af20uCoTmw3mNfZ6QUbzB3Ab8Y DgukNQhYusURq9a+jvaXL7QstbZQ4DiDlTneeumnqnf2qcP6iu4XTx4hDA6XSOl0LH9R t7Mw== MIME-Version: 1.0 X-Received: by 10.53.12.229 with SMTP id et5mr17500067vdd.32.1402246093801; Sun, 08 Jun 2014 09:48:13 -0700 (PDT) In-Reply-To: <927afb61-be0e-43a1-8aab-107e77a013fc@googlegroups.com> References: <8b96ae27-20fa-4df9-807e-c806fed983c0@googlegroups.com> <1dd863ba-09e5-439b-8669-db65f3e999eb@googlegroups.com> <927afb61-be0e-43a1-8aab-107e77a013fc@googlegroups.com> Date: Mon, 9 Jun 2014 02:48:13 +1000 Subject: Re: Uniform Function Call Syntax (UFCS) From: Chris Angelico Cc: "python-list@python.org" Content-Type: text/plain; charset=UTF-8 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: 77 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1402246096 news.xs4all.nl 2895 [2001:888:2000:d::a6]:40943 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:72974 On Mon, Jun 9, 2014 at 1:39 AM, jongiddy wrote: > e.g. I could define: > > def squared(x): > return x * x > > i = 3 > i.squared() => 9 > > j = AClassThatImplements__mul__() > j.squared() => whatever j * j returns > > but also: > class AnotherClass: > def __mul__(self, other): > ... > def squared(self): > return specialised_method_for_calculating_squares() > > k = AnotherClass() > k.squared() => calls method, not function > > In this case, there is a problem with letting hasattr('squared') return True for these first two instances. See Ian's post for a description of the problem. class Circle: def squared(self): raise NotImplementedError("Proven impossible in 1882") The trouble is that logically Circle does have a 'squared' attribute, while 3 doesn't; and yet Python guarantees this: foo.squared() # is equivalent [1] to func = foo.squared func() Which means that for (3).squared() to be 9, it has to be possible to evaluate (3).squared, which means that hasattr (which is defined by attempting to get the attribute and seeing if an exception is thrown) has to return True. Except that it's even more complicated than that, because hasattr wasn't defined in your module, so it has a different set of globals. In fact, this would mean that hasattr would become quite useless. (Hmm, PEP 463 might become a prerequisite of your proposal...) It also means that attribute lookup becomes extremely surprising any time the globals change; currently, "x.y" means exactly the same thing for any given object x and attribute y, no matter where you do it. The only way I can think of for all this to make sense is actually doing it the other way around. Instead of having x.y() fall back on y(x), have y(x) attempt x.y() first. To pull this off, you'd need a special bouncer around every global or builtin... which may be tricky. class MagicDict(dict): def __getitem__(self, item): # If this throws, let the exception propagate obj = super().__getitem__(item) if not callable(obj): return obj def bouncer(*a, **kw): if len(a)==1 and not kw: try: return getattr(a[0], item)() except AttributeError: pass return obj(*a, **kw) return bouncer import __main__ # Except that this bit doesn't work. __main__.__dict__ = MagicDict(__main__.__dict__) It's theoretically possible, along these lines, I think. Whether it's actually any good or not is another question, though! ChrisA [1] Modulo performance. CPython, AFAIK, does this exactly as written, but other Pythons may and do optimize the actual "foo.squared()" form to reduce heap usage. But in terms of visible effects, equivalent.