On 9 March 2015 at 22:40, Andrew Barnert
On Mar 8, 2015, at 5:22 PM, Nick Coghlan
wrote: On 9 Mar 2015 10:12, "Nick Coghlan"
wrote: On 9 Mar 2015 03:18, "Mark Young"
wrote: Thanks Nick! I swear I checked on the 3.x "Data Model" page, but I guess not.
Every other reference on that page is to the class attribute rather than the implicit method nonlocal, so it took a moment for me to relocate it myself. I should have searched for "super" instead :)
With the benefit of hindsight, if I had the chance to do this over, I'd suggest we call the implicit method nonlocal "__classdef__" instead, specifically to avoid the name collision with the runtime type information on object instances. My general impression is that the current name triggers too many incorrect assumptions for most readers, and the name collision makes it harder than it needs to be to build a more correct mental model.
I can tell you that every single time I've mentioned the __class__ nonlocal in a StackOverflow answer, someone mistakenly "corrected" me to tell me either "you need to write self.__class__" or "that won't work because it's the runtime type of self, which could be a subclass".
I think a better solution, if you were doing it from scratch, might be to get rid of the __class__ member and force people to use type(self) to get it, so TOOTDI.
They're not substitutes for each other, as __class__ lets you lie about your type to the consumer, while type() doesn't, and this is by design:
import weakref class Example(): ... pass ... a = Example() b = weakref.proxy(a) b.__class__
type(b)
For many use cases, you actually want obj.__class__ in order to handle proxy objects correctly.
(Of course that implies that code that needs to change __class__ would have to call some function to do so, but I'm not sure that's a bad thing. Dynamically changing your type is a rare thing to do in Python, and unusual or impossible in most other OO languages, except maybe during initialization in the Smalltalk family, so why shouldn't it be signaled by something scary?)
It's not (just) about being able to dynamically change your type, it's about the fact that __class__ goes through the descriptor and class attribute lookup machinery, while type() doesn't.
On the other hand, is __class__ the only thing that's spelled with double underscored that isn't an attribute? Maybe that's the part that's confusing people...
It's not the only one - implicit module attributes like __name__ work that way, as do the __debug__ and __import__ builtins. As far as I can tell, it's specifically the fact that "__class__" looks like a plausible typo for "self.__class__" that causes problems, as this also creates the problem that if you search for "__class__" not only on the data model page, but anywhere, you're far more likely to get a hit on the attribute (which has been around for as long as Python has had classes) than you will on the implicit method nonlocal introduced in Python 3. Hence why I suspect changing/aliasing the preferred name for referencing the nonlocal to be __classdef__ may help improve things, as it better hints at the lexical scoping, where you're referring to the class where the method is being defined at compile time, rather than the one where it was retrieved at run time. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia