Home | History | Annotate | Download | only in metaclasses
      1 Subject: Re: The metaclass saga using Python
      2 From: Vladimir Marangozov <Vladimir.Marangozov (a] imag.fr>
      3 To: tim_one (a] email.msn.com (Tim Peters)
      4 Cc: python-list (a] 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 (a] inrialpes.fr
    256 http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252
    257