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