| Guido van Rossum | a9ca42d | 1998-08-10 01:56:14 +0000 | [diff] [blame] | 1 | Subject: Re: The metaclass saga using Python | 
 | 2 | From: Vladimir Marangozov <Vladimir.Marangozov@imag.fr> | 
 | 3 | To: tim_one@email.msn.com (Tim Peters) | 
 | 4 | Cc: python-list@cwi.nl | 
 | 5 | Date: Wed, 5 Aug 1998 15:59:06 +0200 (DFT) | 
 | 6 |  | 
 | 7 | [Tim] | 
 | 8 | >  | 
 | 9 | > building-on-examples-tends-to-prevent-abstract-thrashing-ly y'rs  - tim | 
 | 10 | >  | 
 | 11 |  | 
 | 12 | OK, I stand corrected. I understand that anybody's interpretation of | 
 | 13 | the meta-class concept is likely to be difficult to digest by others. | 
 | 14 |  | 
 | 15 | Here's another try, expressing the same thing, but using the Python | 
 | 16 | programming model, examples and, perhaps, more popular terms. | 
 | 17 |  | 
 | 18 | 1. Classes. | 
 | 19 |  | 
 | 20 |    This is pure Python of today. Sorry about the tutorial, but it is | 
 | 21 |    meant to illustrate the second part, which is the one we're | 
 | 22 |    interested in and which will follow the same development scenario. | 
 | 23 |    Besides, newbies are likely to understand that the discussion is | 
 | 24 |    affordable even for them :-) | 
 | 25 |  | 
 | 26 |    a) Class definition | 
 | 27 |  | 
 | 28 |       A class is meant to define the common properties of a set of objects. | 
 | 29 |       A class is a "package" of properties. The assembly of properties | 
 | 30 |       in a class package is sometimes called a class structure (which isn't | 
 | 31 |       always appropriate). | 
 | 32 |  | 
 | 33 |       >>> class A: | 
 | 34 |               attr1 = "Hello"                  # an attribute of A | 
 | 35 |               def method1(self, *args): pass   # method1 of A | 
 | 36 |               def method2(self, *args): pass   # method2 of A | 
 | 37 |       >>> | 
 | 38 |  | 
 | 39 |       So far, we defined the structure of the class A. The class A is | 
 | 40 |       of type <class>. We can check this by asking Python: "what is A?" | 
 | 41 |  | 
 | 42 |       >>> A                                # What is A? | 
 | 43 |       <class __main__.A at 2023e360> | 
 | 44 |  | 
| Guido van Rossum | 482e82a | 1998-08-10 13:18:11 +0000 | [diff] [blame] | 45 |    b) Class instantiation | 
| Guido van Rossum | a9ca42d | 1998-08-10 01:56:14 +0000 | [diff] [blame] | 46 |  | 
 | 47 |       Creating an object with the properties defined in the class A is | 
| Guido van Rossum | 482e82a | 1998-08-10 13:18:11 +0000 | [diff] [blame] | 48 |       called instantiation of the class A. After an instantiation of A, we | 
| Guido van Rossum | a9ca42d | 1998-08-10 01:56:14 +0000 | [diff] [blame] | 49 |       obtain a new object, called an instance, which has the properties | 
 | 50 |       packaged in the class A. | 
 | 51 |  | 
 | 52 |       >>> a = A()                          # 'a' is the 1st instance of A  | 
 | 53 |       >>> a                                # What is 'a'?  | 
 | 54 |       <__main__.A instance at 2022b9d0> | 
 | 55 |  | 
 | 56 |       >>> b = A()                          # 'b' is another instance of A | 
 | 57 |       >>> b                                # What is 'b'? | 
 | 58 |       <__main__.A instance at 2022b9c0> | 
 | 59 |  | 
 | 60 |       The objects, 'a' and 'b', are of type <instance> and they both have | 
 | 61 |       the same properties. Note, that 'a' and 'b' are different objects. | 
 | 62 |       (their adresses differ). This is a bit hard to see, so let's ask Python: | 
 | 63 |  | 
 | 64 |       >>> a == b                           # Is 'a' the same object as 'b'? | 
 | 65 |       0                                    # No. | 
 | 66 |  | 
 | 67 |       Instance objects have one more special property, indicating the class | 
 | 68 |       they are an instance of. This property is named __class__. | 
 | 69 |  | 
 | 70 |       >>> a.__class__                      # What is the class of 'a'? | 
 | 71 |       <class __main__.A at 2023e360>       # 'a' is an instance of A | 
 | 72 |       >>> b.__class__                      # What is the class of 'b'? | 
 | 73 |       <class __main__.A at 2023e360>       # 'b' is an instance of A | 
 | 74 |       >>> a.__class__ == b.__class__       # Is it really the same class A? | 
 | 75 |       1                                    # Yes. | 
 | 76 |  | 
 | 77 |    c) Class inheritance (class composition and specialization) | 
 | 78 |  | 
 | 79 |       Classes can be defined in terms of other existing classes (and only | 
 | 80 |       classes! -- don't bug me on this now). Thus, we can compose property | 
 | 81 |       packages and create new ones. We reuse the property set defined | 
 | 82 |       in a class by defining a new class, which "inherits" from the former. | 
 | 83 |       In other words, a class B which inherits from the class A, inherits | 
 | 84 |       the properties defined in A, or, B inherits the structure of A. | 
 | 85 |  | 
 | 86 |       In the same time, at the definition of the new class B, we can enrich | 
 | 87 |       the inherited set of properties by adding new ones and/or modify some | 
 | 88 |       of the inherited properties. | 
 | 89 |        | 
 | 90 |       >>> class B(A):                          # B inherits A's properties | 
 | 91 |               attr2 = "World"                  # additional attr2 | 
 | 92 |               def method2(self, arg1): pass    # method2 is redefined | 
 | 93 |               def method3(self, *args): pass   # additional method3 | 
 | 94 |  | 
 | 95 |       >>> B                                 # What is B? | 
 | 96 |       <class __main__.B at 2023e500> | 
 | 97 |       >>> B == A                            # Is B the same class as A? | 
 | 98 |       0                                     # No. | 
 | 99 |  | 
 | 100 |       Classes define one special property, indicating whether a class | 
 | 101 |       inherits the properties of another class. This property is called | 
 | 102 |       __bases__ and it contains a list (a tuple) of the classes the new | 
 | 103 |       class inherits from. The classes from which a class is inheriting the | 
 | 104 |       properties are called superclasses (in Python, we call them also -- | 
 | 105 |       base classes). | 
 | 106 |  | 
 | 107 |       >>> A.__bases__                       # Does A have any superclasses? | 
 | 108 |       ()                                    # No. | 
 | 109 |       >>> B.__bases__                       # Does B have any superclasses? | 
 | 110 |       (<class __main__.A at 2023e360>,)     # Yes. It has one superclass. | 
 | 111 |       >>> B.__bases__[0] == A               # Is it really the class A? | 
 | 112 |       1                                     # Yes, it is. | 
 | 113 |  | 
 | 114 | -------- | 
 | 115 |  | 
 | 116 |    Congratulations on getting this far! This was the hard part. | 
 | 117 |    Now, let's continue with the easy one. | 
 | 118 |  | 
 | 119 | -------- | 
 | 120 |  | 
 | 121 | 2. Meta-classes | 
 | 122 |  | 
 | 123 |    You have to admit, that an anonymous group of Python wizards are | 
 | 124 |    not satisfied with the property packaging facilities presented above. | 
 | 125 |    They say, that the Real-World bugs them with problems that cannot be | 
 | 126 |    modelled successfully with classes. Or, that the way classes are | 
 | 127 |    implemented in Python and the way classes and instances behave at | 
 | 128 |    runtime isn't always appropriate for reproducing the Real-World's | 
 | 129 |    behavior in a way that satisfies them. | 
 | 130 |  | 
 | 131 |    Hence, what they want is the following: | 
 | 132 |  | 
 | 133 |       a) leave objects as they are (instances of classes) | 
 | 134 |       b) leave classes as they are (property packages and object creators) | 
 | 135 |  | 
 | 136 |    BUT, at the same time: | 
 | 137 |  | 
 | 138 |       c) consider classes as being instances of mysterious objects. | 
 | 139 |       d) label mysterious objects "meta-classes". | 
 | 140 |  | 
 | 141 |    Easy, eh? | 
 | 142 |  | 
 | 143 |    You may ask: "Why on earth do they want to do that?". | 
 | 144 |    They answer: "Poor soul... Go and see how cruel the Real-World is!". | 
 | 145 |    You - fuzzy: "OK, will do!" | 
 | 146 |  | 
 | 147 |    And here we go for another round of what I said in section 1 -- Classes. | 
 | 148 |  | 
 | 149 |    However, be warned! The features we're going to talk about aren't fully | 
 | 150 |    implemented yet, because the Real-World don't let wizards to evaluate | 
 | 151 |    precisely how cruel it is, so the features are still highly-experimental. | 
 | 152 |  | 
 | 153 |    a) Meta-class definition | 
 | 154 |  | 
 | 155 |       A meta-class is meant to define the common properties of a set of | 
 | 156 |       classes.  A meta-class is a "package" of properties. The assembly | 
 | 157 |       of properties in a meta-class package is sometimes called a meta-class | 
 | 158 |       structure (which isn't always appropriate). | 
 | 159 |  | 
 | 160 |       In Python, a meta-class definition would have looked like this: | 
 | 161 |  | 
 | 162 |       >>> metaclass M: | 
 | 163 |               attr1 = "Hello"                  # an attribute of M | 
 | 164 |               def method1(self, *args): pass   # method1 of M | 
 | 165 |               def method2(self, *args): pass   # method2 of M | 
 | 166 |       >>> | 
 | 167 |  | 
 | 168 |       So far, we defined the structure of the meta-class M. The meta-class | 
 | 169 |       M is of type <metaclass>. We cannot check this by asking Python, but | 
 | 170 |       if we could, it would have answered: | 
 | 171 |  | 
 | 172 |       >>> M                                # What is M? | 
 | 173 |       <metaclass __main__.M at 2023e4e0> | 
 | 174 |  | 
| Guido van Rossum | 482e82a | 1998-08-10 13:18:11 +0000 | [diff] [blame] | 175 |    b) Meta-class instantiation | 
| Guido van Rossum | a9ca42d | 1998-08-10 01:56:14 +0000 | [diff] [blame] | 176 |  | 
 | 177 |       Creating an object with the properties defined in the meta-class M is | 
| Guido van Rossum | 482e82a | 1998-08-10 13:18:11 +0000 | [diff] [blame] | 178 |       called instantiation of the meta-class M. After an instantiation of M, | 
| Guido van Rossum | a9ca42d | 1998-08-10 01:56:14 +0000 | [diff] [blame] | 179 |       we obtain a new object, called an class, but now it is called also | 
 | 180 |       a meta-instance, which has the properties packaged in the meta-class M. | 
 | 181 |  | 
 | 182 |       In Python, instantiating a meta-class would have looked like this: | 
 | 183 |  | 
 | 184 |       >>> A = M()                          # 'A' is the 1st instance of M | 
 | 185 |       >>> A                                # What is 'A'? | 
 | 186 |       <class __main__.A at 2022b9d0> | 
 | 187 |  | 
 | 188 |       >>> B = M()                          # 'B' is another instance of M | 
 | 189 |       >>> B                                # What is 'B'? | 
 | 190 |       <class __main__.B at 2022b9c0> | 
 | 191 |  | 
 | 192 |       The metaclass-instances, A and B, are of type <class> and they both | 
 | 193 |       have the same properties. Note, that A and B are different objects. | 
 | 194 |       (their adresses differ). This is a bit hard to see, but if it was | 
 | 195 |       possible to ask Python, it would have answered: | 
 | 196 |  | 
 | 197 |       >>> A == B                           # Is A the same class as B? | 
 | 198 |       0                                    # No. | 
 | 199 |  | 
 | 200 |       Class objects have one more special property, indicating the meta-class | 
 | 201 |       they are an instance of. This property is named __metaclass__. | 
 | 202 |  | 
 | 203 |       >>> A.__metaclass__                  # What is the meta-class of A? | 
 | 204 |       <metaclass __main__.M at 2023e4e0>   # A is an instance of M | 
 | 205 |       >>> A.__metaclass__                  # What is the meta-class of B? | 
 | 206 |       <metaclass __main__.M at 2023e4e0>   # B is an instance of M | 
 | 207 |       >>> A.__metaclass__ == B.__metaclass__  # Is it the same meta-class M? | 
 | 208 |       1                                    # Yes. | 
 | 209 |  | 
 | 210 |    c) Meta-class inheritance (meta-class composition and specialization) | 
 | 211 |  | 
 | 212 |       Meta-classes can be defined in terms of other existing meta-classes | 
 | 213 |       (and only meta-classes!). Thus, we can compose property packages and | 
 | 214 |       create new ones. We reuse the property set defined in a meta-class by | 
 | 215 |       defining a new meta-class, which "inherits" from the former. | 
 | 216 |       In other words, a meta-class N which inherits from the meta-class M, | 
 | 217 |       inherits the properties defined in M, or, N inherits the structure of M. | 
 | 218 |  | 
 | 219 |       In the same time, at the definition of the new meta-class N, we can | 
 | 220 |       enrich the inherited set of properties by adding new ones and/or modify | 
 | 221 |       some of the inherited properties. | 
 | 222 |  | 
 | 223 |       >>> metaclass N(M):                      # N inherits M's properties | 
 | 224 |               attr2 = "World"                  # additional attr2 | 
 | 225 |               def method2(self, arg1): pass    # method2 is redefined | 
 | 226 |               def method3(self, *args): pass   # additional method3 | 
 | 227 |  | 
 | 228 |       >>> N                              # What is N? | 
 | 229 |       <metaclass __main__.N at 2023e500> | 
 | 230 |       >>> N == M                         # Is N the same meta-class as M? | 
 | 231 |       0                                  # No. | 
 | 232 |  | 
 | 233 |       Meta-classes define one special property, indicating whether a | 
 | 234 |       meta-class inherits the properties of another meta-class. This property | 
 | 235 |       is called __metabases__ and it contains a list (a tuple) of the | 
 | 236 |       meta-classes the new meta-class inherits from. The meta-classes from | 
 | 237 |       which a meta-class is inheriting the properties are called | 
 | 238 |       super-meta-classes (in Python, we call them also -- super meta-bases). | 
 | 239 |  | 
 | 240 |       >>> M.__metabases__                # Does M have any supermetaclasses? | 
 | 241 |       ()                                 # No. | 
 | 242 |       >>> N.__metabases__                # Does N have any supermetaclasses? | 
 | 243 |       (<metaclass __main__.M at 2023e360>,)  # Yes. It has a supermetaclass. | 
| Guido van Rossum | 482e82a | 1998-08-10 13:18:11 +0000 | [diff] [blame] | 244 |       >>> N.__metabases__[0] == M        # Is it really the meta-class M? | 
| Guido van Rossum | a9ca42d | 1998-08-10 01:56:14 +0000 | [diff] [blame] | 245 |       1                                  # Yes, it is. | 
 | 246 |  | 
 | 247 | -------- | 
 | 248 |  | 
 | 249 |    Triple congratulations on getting this far! | 
 | 250 |    Now you know everything about meta-classes and the Real-World! | 
 | 251 |  | 
 | 252 | <unless-wizards-want-meta-classes-be-instances-of-mysterious-objects!> | 
 | 253 |  | 
 | 254 | --  | 
 | 255 |        Vladimir MARANGOZOV          | Vladimir.Marangozov@inrialpes.fr | 
 | 256 | http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252 |