On Mon, 09 Jun 2014 02:48:13 +1000, Chris Angelico wrote: > 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,
Given UFCS, that ought to return the global squared function, curried with 3 as its first (and only) argument. UFCS would be a pretty big design change to Python, but I don't think it would be a *problem* as such. It just means that x.y, hasattr(x, y) etc. would mean something different to what they currently mean. > which means that hasattr (which is defined by > attempting to get the attribute and seeing if an exception is thrown) > has to return True. Yes. And this is a problem why? Obviously it would mean that the semantics of hasattr will be different than they are now, but it's still a coherent set of semantics. In fact, one can already give a class a __getattr__ method which provides UFCS functionality. (Hmmm, you need a way to get the caller's globals. You know, this keeps coming up. I think it's high-time Python offered this as a supported function.) That's no more a problem than any other dynamically generated attribute. Stick that __getattr__ in object itself, and UFCS is now language wide. That would make an awesome hack for anyone wanting to experiment with this! > 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. hasattr doesn't care about globals, nor does it need to. hasattr behaves like the equivalent to: def hasattr(obj, name): try: obj.name except AttributeError: return False return True give or take. And yes, if accessing your attribute has side effects, using hasattr does too: py> class Spam(object): ... @property ... def spam(self): ... print("Spam spam spam spam LOVERLY SPAAAAM!!!!") ... return "spam" ... py> x = Spam() py> hasattr(x, "spam") Spam spam spam spam LOVERLY SPAAAAM!!!! True If that's a worry to you, you can try inspect.getattr_static. > 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. *cough* class Example: def __getattr__(self, name): if name == 'module_name': if __name__ == '__main__': return "NOBODY expects the Spanish Inquisition!" else: return __name__ raise AttributeError("no attribute %r" % name) :-) -- Steven D'Aprano http://import-that.dreamwidth.org/ -- https://mail.python.org/mailman/listinfo/python-list