[Python-Dev] metaclasses, classes, instances, and proper nomenclature (original) (raw)
Nick Coghlan ncoghlan at gmail.com
Sun Sep 8 12:06:17 CEST 2013
- Previous message: [Python-Dev] metaclasses, classes, instances, and proper nomenclature
- Next message: [Python-Dev] cpython: Issue #18904: test_socket: add inheritance tests using fcntl and FD_CLOEXEC
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 8 Sep 2013 18:38, "Ethan Furman" <ethan at stoneleaf.us> wrote:
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.
No, there's no such thing as a "metaclass method".
Metaclass instance methods are equivalent to hidden class methods - they don't appear in dir() and can't be accessed through instances of the class.
It's only class methods on the metaclass that receive that rather than the class object (new is technically a static method, but still accepts the metaclass as the first argument).
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. class Meta(type): @classmethod def metamethod(mcls): print("I'm a metaclass method!") def clsmethod1(cls): print("I'm a class method! Aren't I?") class Class(metaclass=Meta): @classmethod def clsmethod2(cls): print("I'm a class method for sure!") def instancemethod(self): print("And I'm a regular ol' instance method")
So, is Meta.clsmethod1 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().
It's a hidden class method.
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.
This is exactly how a metaclass is intended to be used - to affect the behaviour of the class without affecting the behaviour of instances.
And yes, introspection does get a little interesting when a non-trivial metaclass is in play :)
Cheers, Nick.
--
Ethan
Python-Dev mailing list Python-Dev at python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.python.org/pipermail/python-dev/attachments/20130908/ee9f1ed2/attachment.html>
- Previous message: [Python-Dev] metaclasses, classes, instances, and proper nomenclature
- Next message: [Python-Dev] cpython: Issue #18904: test_socket: add inheritance tests using fcntl and FD_CLOEXEC
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]