+++ /dev/null
-Subject: Re: The metaclass saga using Python\r
-From: Vladimir Marangozov <Vladimir.Marangozov@imag.fr>\r
-To: tim_one@email.msn.com (Tim Peters)\r
-Cc: python-list@cwi.nl\r
-Date: Wed, 5 Aug 1998 15:59:06 +0200 (DFT)\r
-\r
-[Tim]\r
-> \r
-> building-on-examples-tends-to-prevent-abstract-thrashing-ly y'rs - tim\r
-> \r
-\r
-OK, I stand corrected. I understand that anybody's interpretation of\r
-the meta-class concept is likely to be difficult to digest by others.\r
-\r
-Here's another try, expressing the same thing, but using the Python\r
-programming model, examples and, perhaps, more popular terms.\r
-\r
-1. Classes.\r
-\r
- This is pure Python of today. Sorry about the tutorial, but it is\r
- meant to illustrate the second part, which is the one we're\r
- interested in and which will follow the same development scenario.\r
- Besides, newbies are likely to understand that the discussion is\r
- affordable even for them :-)\r
-\r
- a) Class definition\r
-\r
- A class is meant to define the common properties of a set of objects.\r
- A class is a "package" of properties. The assembly of properties\r
- in a class package is sometimes called a class structure (which isn't\r
- always appropriate).\r
-\r
- >>> class A:\r
- attr1 = "Hello" # an attribute of A\r
- def method1(self, *args): pass # method1 of A\r
- def method2(self, *args): pass # method2 of A\r
- >>>\r
-\r
- So far, we defined the structure of the class A. The class A is\r
- of type <class>. We can check this by asking Python: "what is A?"\r
-\r
- >>> A # What is A?\r
- <class __main__.A at 2023e360>\r
-\r
- b) Class instantiation\r
-\r
- Creating an object with the properties defined in the class A is\r
- called instantiation of the class A. After an instantiation of A, we\r
- obtain a new object, called an instance, which has the properties\r
- packaged in the class A.\r
-\r
- >>> a = A() # 'a' is the 1st instance of A \r
- >>> a # What is 'a'? \r
- <__main__.A instance at 2022b9d0>\r
-\r
- >>> b = A() # 'b' is another instance of A\r
- >>> b # What is 'b'?\r
- <__main__.A instance at 2022b9c0>\r
-\r
- The objects, 'a' and 'b', are of type <instance> and they both have\r
- the same properties. Note, that 'a' and 'b' are different objects.\r
- (their adresses differ). This is a bit hard to see, so let's ask Python:\r
-\r
- >>> a == b # Is 'a' the same object as 'b'?\r
- 0 # No.\r
-\r
- Instance objects have one more special property, indicating the class\r
- they are an instance of. This property is named __class__.\r
-\r
- >>> a.__class__ # What is the class of 'a'?\r
- <class __main__.A at 2023e360> # 'a' is an instance of A\r
- >>> b.__class__ # What is the class of 'b'?\r
- <class __main__.A at 2023e360> # 'b' is an instance of A\r
- >>> a.__class__ == b.__class__ # Is it really the same class A?\r
- 1 # Yes.\r
-\r
- c) Class inheritance (class composition and specialization)\r
-\r
- Classes can be defined in terms of other existing classes (and only\r
- classes! -- don't bug me on this now). Thus, we can compose property\r
- packages and create new ones. We reuse the property set defined\r
- in a class by defining a new class, which "inherits" from the former.\r
- In other words, a class B which inherits from the class A, inherits\r
- the properties defined in A, or, B inherits the structure of A.\r
-\r
- In the same time, at the definition of the new class B, we can enrich\r
- the inherited set of properties by adding new ones and/or modify some\r
- of the inherited properties.\r
- \r
- >>> class B(A): # B inherits A's properties\r
- attr2 = "World" # additional attr2\r
- def method2(self, arg1): pass # method2 is redefined\r
- def method3(self, *args): pass # additional method3\r
-\r
- >>> B # What is B?\r
- <class __main__.B at 2023e500>\r
- >>> B == A # Is B the same class as A?\r
- 0 # No.\r
-\r
- Classes define one special property, indicating whether a class\r
- inherits the properties of another class. This property is called\r
- __bases__ and it contains a list (a tuple) of the classes the new\r
- class inherits from. The classes from which a class is inheriting the\r
- properties are called superclasses (in Python, we call them also --\r
- base classes).\r
-\r
- >>> A.__bases__ # Does A have any superclasses?\r
- () # No.\r
- >>> B.__bases__ # Does B have any superclasses?\r
- (<class __main__.A at 2023e360>,) # Yes. It has one superclass.\r
- >>> B.__bases__[0] == A # Is it really the class A?\r
- 1 # Yes, it is.\r
-\r
---------\r
-\r
- Congratulations on getting this far! This was the hard part.\r
- Now, let's continue with the easy one.\r
-\r
---------\r
-\r
-2. Meta-classes\r
-\r
- You have to admit, that an anonymous group of Python wizards are\r
- not satisfied with the property packaging facilities presented above.\r
- They say, that the Real-World bugs them with problems that cannot be\r
- modelled successfully with classes. Or, that the way classes are\r
- implemented in Python and the way classes and instances behave at\r
- runtime isn't always appropriate for reproducing the Real-World's\r
- behavior in a way that satisfies them.\r
-\r
- Hence, what they want is the following:\r
-\r
- a) leave objects as they are (instances of classes)\r
- b) leave classes as they are (property packages and object creators)\r
-\r
- BUT, at the same time:\r
-\r
- c) consider classes as being instances of mysterious objects.\r
- d) label mysterious objects "meta-classes".\r
-\r
- Easy, eh?\r
-\r
- You may ask: "Why on earth do they want to do that?".\r
- They answer: "Poor soul... Go and see how cruel the Real-World is!".\r
- You - fuzzy: "OK, will do!"\r
-\r
- And here we go for another round of what I said in section 1 -- Classes.\r
-\r
- However, be warned! The features we're going to talk about aren't fully\r
- implemented yet, because the Real-World don't let wizards to evaluate\r
- precisely how cruel it is, so the features are still highly-experimental.\r
-\r
- a) Meta-class definition\r
-\r
- A meta-class is meant to define the common properties of a set of\r
- classes. A meta-class is a "package" of properties. The assembly\r
- of properties in a meta-class package is sometimes called a meta-class\r
- structure (which isn't always appropriate).\r
-\r
- In Python, a meta-class definition would have looked like this:\r
-\r
- >>> metaclass M:\r
- attr1 = "Hello" # an attribute of M\r
- def method1(self, *args): pass # method1 of M\r
- def method2(self, *args): pass # method2 of M\r
- >>>\r
-\r
- So far, we defined the structure of the meta-class M. The meta-class\r
- M is of type <metaclass>. We cannot check this by asking Python, but\r
- if we could, it would have answered:\r
-\r
- >>> M # What is M?\r
- <metaclass __main__.M at 2023e4e0>\r
-\r
- b) Meta-class instantiation\r
-\r
- Creating an object with the properties defined in the meta-class M is\r
- called instantiation of the meta-class M. After an instantiation of M,\r
- we obtain a new object, called an class, but now it is called also\r
- a meta-instance, which has the properties packaged in the meta-class M.\r
-\r
- In Python, instantiating a meta-class would have looked like this:\r
-\r
- >>> A = M() # 'A' is the 1st instance of M\r
- >>> A # What is 'A'?\r
- <class __main__.A at 2022b9d0>\r
-\r
- >>> B = M() # 'B' is another instance of M\r
- >>> B # What is 'B'?\r
- <class __main__.B at 2022b9c0>\r
-\r
- The metaclass-instances, A and B, are of type <class> and they both\r
- have the same properties. Note, that A and B are different objects.\r
- (their adresses differ). This is a bit hard to see, but if it was\r
- possible to ask Python, it would have answered:\r
-\r
- >>> A == B # Is A the same class as B?\r
- 0 # No.\r
-\r
- Class objects have one more special property, indicating the meta-class\r
- they are an instance of. This property is named __metaclass__.\r
-\r
- >>> A.__metaclass__ # What is the meta-class of A?\r
- <metaclass __main__.M at 2023e4e0> # A is an instance of M\r
- >>> A.__metaclass__ # What is the meta-class of B?\r
- <metaclass __main__.M at 2023e4e0> # B is an instance of M\r
- >>> A.__metaclass__ == B.__metaclass__ # Is it the same meta-class M?\r
- 1 # Yes.\r
-\r
- c) Meta-class inheritance (meta-class composition and specialization)\r
-\r
- Meta-classes can be defined in terms of other existing meta-classes\r
- (and only meta-classes!). Thus, we can compose property packages and\r
- create new ones. We reuse the property set defined in a meta-class by\r
- defining a new meta-class, which "inherits" from the former.\r
- In other words, a meta-class N which inherits from the meta-class M,\r
- inherits the properties defined in M, or, N inherits the structure of M.\r
-\r
- In the same time, at the definition of the new meta-class N, we can\r
- enrich the inherited set of properties by adding new ones and/or modify\r
- some of the inherited properties.\r
-\r
- >>> metaclass N(M): # N inherits M's properties\r
- attr2 = "World" # additional attr2\r
- def method2(self, arg1): pass # method2 is redefined\r
- def method3(self, *args): pass # additional method3\r
-\r
- >>> N # What is N?\r
- <metaclass __main__.N at 2023e500>\r
- >>> N == M # Is N the same meta-class as M?\r
- 0 # No.\r
-\r
- Meta-classes define one special property, indicating whether a\r
- meta-class inherits the properties of another meta-class. This property\r
- is called __metabases__ and it contains a list (a tuple) of the\r
- meta-classes the new meta-class inherits from. The meta-classes from\r
- which a meta-class is inheriting the properties are called\r
- super-meta-classes (in Python, we call them also -- super meta-bases).\r
-\r
- >>> M.__metabases__ # Does M have any supermetaclasses?\r
- () # No.\r
- >>> N.__metabases__ # Does N have any supermetaclasses?\r
- (<metaclass __main__.M at 2023e360>,) # Yes. It has a supermetaclass.\r
- >>> N.__metabases__[0] == M # Is it really the meta-class M?\r
- 1 # Yes, it is.\r
-\r
---------\r
-\r
- Triple congratulations on getting this far!\r
- Now you know everything about meta-classes and the Real-World!\r
-\r
-<unless-wizards-want-meta-classes-be-instances-of-mysterious-objects!>\r
-\r
--- \r
- Vladimir MARANGOZOV | Vladimir.Marangozov@inrialpes.fr\r
-http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252\r