[Python-Dev] metaclasses, classes, instances, and proper nomenclature
ethan at stoneleaf.us
Sun Sep 8 09:42:20 CEST 2013
I've run across two different ways to think about this:
1) the type of the first argument
2) where the method/attribute lives
Since attributes don't take a first argument they default to 2: an instance attribute lives in the instance, a class
attribute lives in the class, and a metaclass attribute lives in the metaclass.
Methods, on the other hand, do take a first argument: an instance method takes itself, a class method takes the class,
and a metaclass method takes the metaclass.
Going by option 1 above there is only one way to get an instance method, and only one way to get a metaclass method --
calling with the instance (either directly or indirectly via the class), or calling a metaclass method that has been
marked as a @classmethod.
Therein lies my confusion.
print("I'm a metaclass method!")
print("I'm a class method! Aren't I?")
print("I'm a class method for sure!")
print("And I'm a regular ol' instance method")
So, is Meta.cls_method1 a class method? On the one hand, it takes the class as it's first parameter, on the other hand
it lives in the metaclass. And on the third hand you can't get to it from the instance Class().
If you're wondering why this is posted to PyDev, the related question is this: What is the proper role of a metaclass?
Should it basically fiddle with the class creation process and then get out of the way? The case in point is, of
course, Enum. Currently it has a custom __getattr__, but it lives in the metaclass, EnumMeta. Now this is handy,
because it means that Color.red.blue raises an AttributeError, where if __getattr__ lived in Enum itself that would
work. It also has the __members__ attribute living in EnumMeta, which means it's not accessible from Color.red. In
other words, EnumMeta is not getting out the way, it is still very much involved. On the one hand, that's cool; on the
other hand, I hand to think hard to figure out why Color.red.blue was not getting routed through EnumMeta's __getattr__,
but was instead getting routed through object.__getattr__.
More information about the Python-Dev