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 |
|
---|
45 | b) Class instantiation
|
---|
46 |
|
---|
47 | Creating an object with the properties defined in the class A is
|
---|
48 | called instantiation of the class A. After an instantiation of A, we
|
---|
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 |
|
---|
175 | b) Meta-class instantiation
|
---|
176 |
|
---|
177 | Creating an object with the properties defined in the meta-class M is
|
---|
178 | called instantiation of the meta-class M. After an instantiation of M,
|
---|
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.
|
---|
244 | >>> N.__metabases__[0] == M # Is it really the meta-class M?
|
---|
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
|
---|