summaryrefslogtreecommitdiff
path: root/pypers/meta.txt
blob: 31adcf4d6eb19f4cc253a25e089cd476c0369451 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
THE MAGIC OF METACLASSES - PART I
==========================================================================

 .. line-block::

    *Metaclasses are deeper magic than 99% of users should ever
    worry about.  If you wonder whether you need them, you don't
    (the people who actually need them know with certainty that
    they need them, and don't need an explanation about why).*
    --Tim Peters

Python always had metaclasses, since they are inherent to its object
model. However, before Python 2.2, metaclasses where tricky and their
study could cause the programmer's brain to explode [#]_. Nowadays, 
the situation has changed, and the reader should be able to understand 
this chapter without risk for his/her brain (however I do not give any 
warranty ;)

Put it shortly, metaclasses give to the Python programmer
complete control on the creation of classes. This simple statement
has far reaching consequences, since the ability of interfering with
the process of class creation, enable the programmer to make miracles.

In this and in the following chapters, I will show some of these
miracles.

This chapter will focus on subtle problems of metaclasses in inheritance
and multiple inheritance, including multiple inheritance of metaclasses
with classes and metaclasses with metaclasses.

The next chapter will focus more on applications.


.. [#] Metaclasses in Python 1.5 [A.k.a the killer joke] 
       http://www.python.org/doc/essays/metaclasses/

There is very little documentation about metaclasses, except Guido's
essays and the papers by David Mertz and myself published in IBMdeveloperWorks

  http://www-106.ibm.com/developerworks/library/l-pymeta.html

Metaclasses as class factories
------------------------------------------------------------------------

In the Python object model (inspired from the Smalltalk, that had metaclasses 
a quarter of century ago!) classes themselves are objects. 
Now, since objects are instances of classes, that means that classes 
themselves can be seen as instances of special classes called *metaclasses*.
Notice that things get hairy soon, since by following this idea, one could 
say the metaclasses themselves are classes and therefore objects;  that 
would mean than even metaclasses can be seen as 
instances of special classes called meta-metaclasses. On the other hand,
meta-meta-classes can be seen as instances of meta-meta-metaclasses,
etc. Now, it should be obvious why metaclasses have gained such a 
reputation of brain-exploders ;). However, fortunately, the situation 
is not so bad in practice, since the infinite recursion of metaclasses is 
avoided because there is a metaclass that is the "mother of all metaclasses": 
the built-in metaclass *type*. 'type' has the property of being its own 
metaclass, therefore the recursion stops. Consider for instance the following
example:

  >>> class C(object): pass # a generic class
  >>> type(C) #gives the metaclass of C
  <type 'type'>
  >>> type(type(C)) #gives the metaclass of type
  <type 'type'>

The recursion stops, since the metaclass of 'type' is 'type'.
One cool consequence of classes being instances of 'type', 
is that since *type* is a subclass of object,

  >>> issubclass(type,object)
  True 

any Python class is not only a subclass of ``object``, but also
an instance of 'object':

  >>> isinstance(C,type)
  True
  >>> isinstance(C,object) 
  True
  >>> issubclass(C,object) 
  True

Notice that 'type' is an instance of itself (!) and therefore of 'object':

  >>> isinstance(type,type) # 'type' is an instance of 'type'
  True
  >>> isinstance(type,object) # therefore 'type' is an instance of 'object'
  True

As it is well known, ``type(X)`` returns the type of ``X``; however, 
``type`` has also a second form in which it acts as a class factory.
The form is ``type(name,bases,dic)`` where ``name`` is the name of
the new class to be created, bases is the tuple of its bases and dic
is the class dictionary. Let me give a few examples:

  >>> C=type('C',(),{})
  >>> C
  <class '__main__.C'>
  >>> C.__name__
  'C'
  >>> C.__bases__
  (<type 'object'>,)
  >>> C.__dict__
  <dict-proxy object at 0x8109054>

Notice that since all metaclasses inherits from ``type``, as a consequences
all metaclasses can be used as class factories. 

A fairy tale example will help in understanding the concept
and few subtle points on how attributes are transmitted from metaclasses
to their instances.

Let me start by defining a 'Nobility' metaclass :

  >>> class Nobility(type): attributes="Power,Richness,Beauty"

instances of 'Nobility' are classes such 'Princes', 'Dukes', 'Barons', etc.

  >>> Prince=Nobility("Prince",(),{})

Instances of 'Nobility' inherits its attributes, just as instances of normal
classes inherits the class docstring:

  >>> Prince.attributes
  'Power,Richness,Beauty'

Nevertheless, 'attributes' will not be retrieved by the ``dir`` function:

  >>> print dir(Prince)
  ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', 
   '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__repr__', 
   '__setattr__', '__str__', '__weakref__']

However, this is a limitation of ``dir``, in reality ``Prince.attributes``
is there. On the other hand, the situation is different for a specific 
'Prince' object

  >>> charles=Prince()
  >>> charles.attributes #error
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
  AttributeError: 'Prince' object has no attribute 'attributes'

The transmission of metaclass attributes is not transitive:
instances of the metaclass inherits the attributes, but not the instances 
of the instances. This behavior is by design and is needed in order to avoid 
troubles with special methods. This point will be throughly 
explained in the last paragraph. For the moment, I my notice that the
behaviour is reasonable, since the abstract qualities  'Power,Richness,Beauty'
are more qualities of the 'Prince' class than of one specific representative.
They can always be retrieved via the ``__class__`` attribute:

  >>> charles.__class__.attributes
  'Power,Richness,Beauty'

Le me now define a metaclass 'Froggyness':

  >>> class Frogginess(type): attributes="Powerlessness,Poverty,Uglyness"

Instances of 'Frogginess' are classes like 'Frog', 'Toad', etc.

  >>> Frog=Frogginess("Frog",(),{})
  >>> Frog.attributes
  'Powerlessness,Poverty,Uglyness'

However, in Python miracles can happen:

  >>> def miracle(Frog): Frog.__class__=Nobility
  >>> miracle(Frog); Frog.attributes
  'Powerlessness,Richness,Beauty'

In this example a miracle happened on the class 'Frog', by changing its
(meta)class to 'Nobility'; therefore its attributes have changed accordingly.

However, there is subtle point here. Suppose we explicitly specify the 'Frog'
attributes, in such a way that it can be inherited by one of its specific
representative:

  >>> Frog.attributes="poor, small, ugly"
  >>> jack=Frog(); jack.attributes
  'poor, small, ugly'

Then the miracle cannot work:

 ::

  #<fairytale2.py>

  class Nobility(type): attributes="Power, Richness, Beauty"
  Prince=Nobility("Prince",(),{})
  charles=Prince()

  class Frogginess(type): attributes="Inpuissance, Poverty, Uglyness"
  Frog=Frogginess("Frog",(),{})
  Frog.attributes="poor, small, ugly"
  jack=Frog()

  def miracle(Frog): Frog.__class__=Nobility

  miracle(Frog)

  print "I am",Frog.attributes,"even if my class is",Frog.__class__

  #</fairytale2.py>

Output:

 ::

  I am poor, small, ugly even if my class is <class '__main__.Nobility'>

The reason is that Python first looks at specific attributes of an object
(in this case the object is the class 'Frog') an only if they are not found, 
it looks at the attributes of its class (here the metaclass 'Nobility').Since 
in this example the 'Frog' class has explicit attributes, the
result is ``poor, small, ugly``. If you think a bit, it makes sense.

Remark:

In Python 2.3 there are restrictions when changing the ``__class__`` 
attribute for classes:

  >>> C=type('C',(),{})
  >>> C.__class__ = Nobility #error
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
  TypeError: __class__ assignment: only for heap types

Here changing ``C.__class__`` is not allowed, since 'C' is an instance
of the built-in metaclass 'type'. This restriction, i.e. the fact that 
the built-in metaclass cannot be changed, has been imposed for
security reasons, in order to avoid dirty tricks with the built-in
classes. For instance, if it was possible to change the metaclass
of the 'bool' class, we could arbitrarily change the behavior of
boolean objects. This could led to abuses. 
Thanks to this restriction,
the programmer is always sure that built-in classes behaves as documented.
This is also the reason why 'bool' cannot be subclassed:

  >>> print bool.__doc__ # in Python 2.2 would give an error
  bool(x) -> bool
  Returns True when the argument x is true, False otherwise.
  The builtins True and False are the only two instances of the class bool.
  The class bool is a subclass of the class int, and cannot be subclassed.

In any case, changing the class of a class is not a good idea, since it
does not play well with inheritance, i.e. changing the metaclass of a base 
class does not change the metaclass of its children:

  >>> class M1(type): f=lambda cls: 'M1.f' #metaclass1
  >>> class M2(type): f=lambda cls: 'M2.f' #metaclass2
  >>> B=M1('B',(),{}) # B receives M1.f
  >>> class C(B): pass #C receives M1.f
  >>> B.f()
  'M1.f'
  B.__class__=M2 #change the metaclass
  >>> B.f() #B receives M2.f
  'M2.f'
  C.f() #however C does *not* receive M2.f
  >>> C.f()
  'M1.f'
  >>> type(B)
  <class '__main__.M2'>
  >>> type(C)
  <class '__main__.M1'>

Metaclasses as class modifiers
----------------------------------------------------------------------  

The interpretation of metaclasses in terms of class factories is quite
straightforward and I am sure that any Pythonista will be at home 
with the concept. However, metaclasses have such a reputation of black 
magic since their typical usage is *not* as class factories, but as 
*class modifiers*. This means that metaclasses are typically
used to modify *in fieri* classes. The trouble is that the
modification can be utterly magical.
Here there is another fairy tale example showing the syntax
(via the ``__metaclass__`` hook) and the magic of the game:

 ::

  #<oopp.py>

  class UglyDuckling(PrettyPrinted):
      "A plain, regular class"
      formatstring="Not beautiful, I am %s"

  class MagicallyTransformed(type):
      "Metaclass changing the formatstring of its instances"
      def __init__(cls,*args):
          cls.formatstring="Very beautiful, since I am %s"
          
  class TransformedUglyDuckling(PrettyPrinted):
      "A class metamagically modified"
      __metaclass__ = MagicallyTransformed
      formatstring="Not beautiful, I am %s" # will be changed

  #</oopp.py>

  >>> from oopp import *
  >>> print UglyDuckling()
  Not beautiful, I am <UglyDuckling>

In this example, even if in 'TransformedUglyDuckling' we explicitely
set the formatstring to  "Not beautiful, I am %s", the metaclass changes 
it to "Very beautiful, even if I am %s" and thus

  >>> print TransformedUglyDuckling() # gives
  Very beautiful, since I am <TransformedUglyDuckling>

Notice that the ``__metaclass__`` hook passes to the metaclass 
``MagicallyTransformed`` the name, bases and dictionary of the class 
being created, i.e. 'TransformedUglyDucking'.

Metaclasses, when used as class modifiers, act *differently*
from functions, when inheritance is
involved. To clarify this subtle point, consider a subclass 'Swan' 
of 'UglyDuckling':


  >>> from oopp import *
  >>> class Swan(UglyDuckling): 
  ...     formatstring="Very beautiful, I am %s"
  >>> print Swan()
  Very beautiful, I am <Swan>

Now, let me define a simple function acting as a class modifier:

  >>> def magicallyTransform(cls): 
  ...    "Modifies the class formatstring"
  ...    customize(cls,formatstring="Very beautiful, even if I am %s")
  ...    return cls

The function works:

  >>> magicallyTransform(UglyDuckling)
  >>> print UglyDuckling()
  Very beautiful, even if I am <UglyDuckling>

This approach is destructive, since we cannot have the original 
and the transformed class at the same time, and has potentially bad side
effects in the derived classes. Nevertheless, in this case it works
and it is not dangereous for the derived class 'Swan', since 'Swan' 
explicitly overrides the 'formatstring' attribute and doesn't care about 
the change in 'UglyDuckling.formatstring'. Therefore the output
of 

  >>> print Swan()
  Very beautiful, I am <Swan>

is still the same as before the action of the function ``magicallyTransform``.
The situation is quite different if we use the 'MagicallyTransformed'
metaclass:

  >>> from oopp import *
  >>> class Swan(TransformedUglyDuckling): 
  ...     formatstring="Very beautiful, I am %s"

  >>> print TransformedUglyDuckling() 
  Very beautiful, since I am <UglyDuckling>
  >>> print Swan() # does *not* print "Very beautiful, I am <Swan>"
  Very beautiful, since I am <Swan> 

Therefore,  not only the metaclass has magically transformed the 
'TransformedUglyDuckling.formatstring', it has also transformed the 
'Swan.formatstring'! And that, despite the fact that 
'Swan.formatstring' is explicitly set. 

The reason for this behaviour is that since 'UglyDuckling' is a base 
class with metaclass 'MagicallyTransformed', and since 'Swan' inherits from
'UglyDuckling', then 'Swan' inherits the metaclass 'MagicallyTransformed',
which is automatically called at 'Swan' creation time.
That's the reason why metaclasses are much more magical and much 
more dangerous than
functions: functions do not override attributes in the derived classes,
metaclasses do, since they are automagically called at the time of
creation of the subclass. In other words, functions are explicit,
metaclasses are implicit. Nevertheless, this behavior can be pretty
useful in many circumstances, and it is a feature, not a bug. In the
situations where this behavior is not intended, one should use a function,
not a metaclass. In general, metaclasses are better than functions,
since metaclasses are classes and as such they can inherit one from each 
other. This means that one can improve a basic metaclass trough 
(multiple) inheritance, with *reuse* of code.

A few caveats about the usage of metaclasses
------------------------------------------------------------------------

Let me start with some caveats about the ``__metaclass__`` hook, which
commonly used and quite powerful, but also quite dangereous. 

Let's imagine a programmer not
knowing about metaclasses and looking at the 'TransformedUglyDuckling'
code (assuming there are no comments): she would probably think
that "__metaclass__" is some special attribute used for introspection
purposes only, with no other effects, and she would probably expect
the output of the script to be "Not much, I am the class 
TransformedUglyDucking" whereas it is exacly the contrary! In other
words, when metaclasses are involved,  *what you see, is not what you get*.
The situation is even more implicit when the metaclass is inherited
from some base class, therefore lacking also the visual clue of the hook.

For these reasons, metaclasses are something to be used with great care; 
they can easily make your code unreadable and confuse inexpert programmers. 
Moreover, it is more difficult to debug programs involving metaclasses, since
methods are magically transformed by routines defined in the metaclass,
and the code you see in the class is *not* what Python sees. I think
the least confusing way of using metaclasses, is to concentrate all
the dynamics on them and to write empty classes except for the
metaclass hook. If you write a class with no methods such as

 ::

  class TransformedUglyDuckling(object):
      __metaclass__=MagicallyTransformed

then the only place to look at, is the metaclass. I have found extremely
confusing to have some of the methods defined in the class and some in
the metaclass, especially during debugging. 

Another point to make, is that the ``__metaclass__``
hook should not be used to modify pre-existing classes, 
since it requires modifying the source code (even if it is enough to 
change one line only). Moreover, it is confusing, since adding a 
``__metaclass__`` attribute *after* the class creation would not do the job:

  >>> from oopp import UglyDuckling, MagicallyTransformed
  >>> UglyDuckling.__metaclass__=MagicallyTransformed
  >>> print UglyDuckling()
  "Not much, I am the class UglyDuckling"

The reason is that we have to think of UglyDuckling as an instance of 
``type``, the built-in metaclasses; merely adding a ``__metaclass__`` 
attribute does not re-initialize the class.
The problem is elegantly solved by avoiding the hook and creating
an enhanced copy of the original class trough ``MagicallyTransformed``
used as a class factory.

  >>> name=UglyDuckling.__name__
  >>> bases=UglyDuckling.__bases__
  >>> dic=UglyDuckling.__dict__.copy()
  >>> UglyDuckling=MagicallyTransformed(name,bases,dic)

Notice that I have recreated 'UglyDuckling', giving to the new class
the old identifier. 

  >>> print UglyDuckling()
  Very beautiful, since I am <UglyDuckling>>

The metaclass of this new 'UglyDuckling' has been specified and will 
accompanies all future children of 'UglyDuckling':

  >>> class Swan(UglyDuckling): pass
  ...
  >>> type(Swan)
  <class '__main__.MagicallyTransformed'>

Another caveat, is in the overridding of `` __init__`` in the metaclass.
This is quite common in the case of metaclasses called trough the
``__metaclass__`` hook mechanism, since in this case the class
has been already defined (if not created) in the class statement,
and we are interested in initializing it, more than in recreating
it (which is still possible, by the way). 
The problem is that overriding ``__init__`` has severe limitations 
with respect to overriding ``__new__``,
since the 'name', 'bases' and 'dic' arguments cannot be directly
changed. Let me show an example:

 ::

  #<init_in_metaclass.py>

  from oopp import *

  class M(type):
      "Shows that dic cannot be modified in __init__, only in __new__"
      def __init__(cls,name,bases,dic):
          name='C name cannot be changed in __init__'
          bases='cannot be changed'
          dic['changed']=True

  class C(object):
      __metaclass__=M
      changed=False

  print C.__name__  # => C
  print C.__bases__ # => (<type 'object'>,)
  print C.changed   # => False

  #</init_in_metaclass.py>

The output of this script is ``False``: the dictionary cannot be changed in 
``__init__`` method. However, replacing ``dic['changed']=True`` with 
``cls.changed=True`` would work. Analougously, changing  ``cls.__name__`` 
would work. On the other hand, ``__bases__`` is a read-only attribute and 
cannot be changed once the class has been created, therefore there is no 
way it can be touched in ``__init__``. However, ``__bases__`` could be
changed in ``__new__`` before the class creation.

Metaclasses and inheritance 
-------------------------------------------------------------------------

It is easy to get confused about the difference between a metaclass
and a mix-in class in multiple inheritance, since 
both are denoted by adjectives and both share the same idea of 
enhancing a hierarchy. Moreover, both mix-in classes and metaclasses 
can be inherited in the whole hierarchy.
Nevertheless, they behaves differently
and there are various subtle point to emphasize. We have already
noticed in the first section that attributes of a metaclass
are transmitted to its instances, but not to the instances of the
instances, whereas the normal inheritance is transitive: the 
grandfather transmits its attributes to the children and to the grandchild 
too. The difference can be represented with the following picture, where
'M' is the metaclass, 'B' a base class, 'C' a children of 'B'
and c an instance of 'C':

 ::

           M (attr)         B (attr)   
           :                |
           C (attr)         C (attr)    
           :                :
           c ()             c (attr)    

Notice that here the relation of instantiation is denoted by a dotted line. 

This picture is valid when C has metaclass M but not base class, on when C
has base class but not metaclass. However, what happens whrn the class C has 
both a metaclass M and a base class B ?

  >>> class M(type): a='M.a'
  >>> class B(object): a='B.a'
  >>> class C(B): __metaclass__=M
  >>> c=C()

The situation can be represented by in the following graph,

 ::

      (M.a)   M   B  (B.a)
              :  /
              : /
         (?)  C
              :
              :
         (?)  c


Here the metaclass M and the base class B are fighting one against the other.
Who wins ? C should inherit the attribute 'B.a' from its base B, however,
the metaclass would like to induce an attribute 'M.a'.
The answer is that the inheritance constraint wins on the metaclass contraint:

  >>> C.a
  'B.a'
  >>> c.a
  'B.a'

The reason is the same we discussed in the fairy tale example: 'M.a' is
an attribute of the metaclass, if its instance C has already a specified
attributed C.a (in this case specified trough inheritance from B), then
the attribute is not modified. However, one could *force* the modification:

  >>> class M(type):
  ...     def __init__(cls,*args): cls.a='M.a'
  >>> class C(B): __metaclass__=M
  >>> C.a
  'M.a'

In this case the metaclass M would win on the base class B. Actually,
this is not surprising, since it is explicit. What could be surprising,
had we not explained why inheritance silently wins, is that

  >>> c.a
  'B.a'

This explain the behaviour for special methods like  
``__new__,__init__,__str__``, 
etc. which are defined both in the class and the metaclass with the same 
name (in both cases,they are inherited from ``object``).

In the chapter on objects, we learned that the printed representation of
an object can be modified by overring the ``__str__`` methods of its
class. In the same sense, the printed representation of a class can be 
modified by overring the ``__str__`` methods of its metaclass. Let me show an 
example:

 ::

  #<oopp.py>

  class Printable(PrettyPrinted,type):
     """Apparently does nothing, but actually makes PrettyPrinted acting as
        a metaclass."""

  #</oopp.py>

Instances of 'Printable' are classes with a nice printable representation:

  >>> from oopp import Printable 
  >>> C=Printable('Classname',(),{})
  >>> print C
  Classname

However, the internal string representation stays the same:

  >>> C # invokes Printable.__repr__
  <class '__main__.Classname'>

Notice that the name of class 'C' is ``Classname`` and not 'C' !

Consider for instance the following code:

  >>> class M(type):
  ...    def __str__(cls):
  ...        return cls.__name__
  ...    def method(cls):
  ...        return cls.__name__
  ...
  >>> class C(object):
  ...    __metaclass__=M
  >>> c=C()

In this case the ``__str__`` method in ``M`` cannot override the 
``__str__`` method in C, which is inherited from ``object``.
Moreover, if you experiment a little, you will see that
 
  >>> print C # is equivalent to print M.__str__(C)
  C
  >>> print c # is equivalent to print C.__str__(c)
  <__main__.C object at 0x8158f54>


The first ``__str__`` is "attached" to the metaclass and the
second to the class. 

Consider now the standard method "method". It is both attached to the
metaclass 

  >>> print M.method(C)
  C

and to the class

  >>> print C.method() #in a sense, this is a class method, i.e. it receives 
  C                    #the class as first argument

Actually it can be seen as a class method of 'C' (cfr. Guido van Rossum
"Unifying types and classes in Python 2.2". When he discusses
classmethods he says: *"Python also has real metaclasses, and perhaps 
methods defined in a metaclass have more right to the name "class method"; 
but I expect that most programmers won't be using metaclasses"*). Actually,
this is the SmallTalk terminology, Unfortunately, in Python the word
``classmethod`` denotes an attribute descriptor, therefore it is better
to call the methods defined in a metaclass *metamethods*, in order to avoid
any possible confusion.

The difference between ``method`` and ``__str__`` is that you cannot use the
syntax

  >>> print C.__str__() #error
  TypeError: descriptor '__str__' of 'object' object needs an argument

because of the confusion with the other __str__; you can only use the
syntax

  >>> print M.__str__(C)

Suppose now I change C's definition by adding a method called "method":

 ::

  class C(object):
      __metaclass__=M
      def __str__(self):
          return "instance of %s" % self.__class__
      def method(self):
          return "instance of %s" % self.__class__

If I do so, then there is name clashing and the previously working
statement print C.method() gives now an error:

 ::

  Traceback (most recent call last):
    File "<stdin>", line 24, in ?
  TypeError: unbound method method() must be called with C instance as
  first argument (got nothing instead)

Conclusion: ``__str__, __new__, __init__`` etc. defined in the metaclass
have name clashing with the standard methods defined in the class, therefore
they must be invoked with the extended syntax (ex. ``M.__str__(C)``),
whereas normal methods in the metaclass with no name clashing with the methods
of the class can be used as class methods (ex. ``C.method()`` instead of
``M.method(C)``).
Metaclass methods are always bound to the metaclass, they bind to the class 
(receiving the class as first argument) only if there is no name clashing with 
already defined methods in the class. Which is the case for ``__str__``,
``___init__``, etc. 

Conflicting metaclasses
----------------------------------------------------------------------------

Consider a class 'A' with metaclass 'M_A' and a class 'B' with 
metaclass 'M_B'; suppose I derive 'C' from 'A' and 'B'. The question is: 
what is the metaclass of 'C' ? Is it 'M_A' or 'M_B' ?

The correct answer (see "Putting metaclasses to work" for a thought 
discussion) is 'M_C', where 'M_C' is a metaclass that inherits from 
'M_A' and 'M_B', as in the following graph:


 .. figure:: fig1.gif

However, Python is not yet that magic, and it does not automatically create 
'M_C'. Instead, it will raise a ``TypeError``, warning the programmer of
the possible confusion:

  >>> class M_A(type): pass
  >>> class M_B(type): pass
  >>> A=M_A('A',(),{})
  >>> B=M_B('B',(),{})
  >>> class C(A,B): pass #error
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
  TypeError: metatype conflict among bases

This is an example where the metaclasses 'M_A' and 'M_B' fight each other
to generate 'C' instead of cooperating. The metatype conflict can be avoided 
by assegning the correct metaclass to 'C' by hand:

  >>> class C(A,B): __metaclass__=type("M_AM_B",(M_A,M_B),{})
  >>> type(C)
  <class '__main__.M_AM_B'>

In general, a class A(B, C, D , ...) can be generated without conflicts only
if type(A) is a  subclass of each of type(B), type(C), ...

In order to avoid conflicts, the following function, that generates
the correct metaclass by looking at the metaclasses of the base
classes, is handy:

 ::

  #<oopp.py>

  metadic={}

  def _generatemetaclass(bases,metas,priority):
      trivial=lambda m: sum([issubclass(M,m) for M in metas],m is type)
      # hackish!! m is trivial if it is 'type' or, in the case explicit
      # metaclasses are given, if it is a superclass of at least one of them
      metabs=tuple([mb for mb in map(type,bases) if not trivial(mb)])
      metabases=(metabs+metas, metas+metabs)[priority]
      if metabases in metadic: # already generated metaclass
          return metadic[metabases]
      elif not metabases: # trivial metabase
          meta=type 
      elif len(metabases)==1: # single metabase
          meta=metabases[0]
      else: # multiple metabases
          metaname="_"+''.join([m.__name__ for m in metabases])
          meta=makecls()(metaname,metabases,{})
      return metadic.setdefault(metabases,meta)

  #</oopp.py>

This function is particularly smart since:

  1. Avoid duplications ..

  2. Remember its results.

We may generate the child of a tuple of base classes with a given metaclass 
and avoiding metatype conflicts thanks to the following ``child`` function:

 ::

  #<oopp.py>

  def makecls(*metas,**options):
      """Class factory avoiding metatype conflicts. The invocation syntax is
      makecls(M1,M2,..,priority=1)(name,bases,dic). If the base classes have 
      metaclasses conflicting within themselves or with the given metaclasses,
      it automatically generates a compatible metaclass and instantiate it. 
      If priority is True, the given metaclasses have priority over the 
      bases' metaclasses"""

      priority=options.get('priority',False) # default, no priority
      return lambda n,b,d: _generatemetaclass(b,metas,priority)(n,b,d)

  #</oopp.py>

Here is an example of usage:

  >>> class C(A,B): __metaclass__=makecls()
  >>> print C,type(C)
  <class 'oopp.AB_'> <class 'oopp._M_AM_B'>

Notice that the automatically generated metaclass does not pollute the 
namespace:

  >>> _M_A_M_B #error
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
  NameError: name '_M_A_M_B' is not defined

It can only be accessed as ``type(C)``.

Put it shortly, the ``child`` function allows to generate a child from bases 
enhanced by different custom metaclasses, by generating under the hood a 
compatibile metaclass via multiple inheritance from the original metaclasses. 
However, this logic can only work if the original metaclasses are
cooperative, i.e. their methods are written in such a way to avoid
collisions. This can be done by using the cooperative the ``super`` call 
mechanism discussed in chapter 4.

Cooperative metaclasses 
----------------------------------------------------------------------------

In this section I will discuss how metaclasses can be composed with
classes and with metaclasses, too. Since we will discuss even
complicated hierarchies, it is convenient to have an utility 
routine printing the MRO of a given class:

 ::

  #<oopp.py>

  def MRO(cls):
      count=0; out=["MRO of %s:" % cls.__name__]
      for c in cls.__mro__:
          name=c.__name__
          bases=','.join([b.__name__ for b in c.__bases__])
          s="  %s - %s(%s)" % (count,name,bases)
          if type(c) is not type: s+="[%s]" % type(c).__name__
          out.append(s); count+=1
      return '\n'.join(out)

  #</oopp.py>

Notice that ``MRO`` also prints the metaclass' name in square brackets, for
classes enhanced by a non-trivial metaclass.

Consider for instance the following hierarchy:

  >>> from oopp import MRO
  >>> class B(object): pass
  >>> class M(B,type): pass
  >>> class C(B): __metaclass__=M

Here 'M' is a metaclass that inherits from 'type' and the base class 'B'
and 'C' is both an instance of 'M' and a child of 'B'. The inheritance
graph can be draw as

 ::

                 object
                 /   \
                B    type
                | \  /
                |  M
                \  :
                 \ :     
                   C
  
Suppose now we want to retrieve the ``__new__`` method of B's superclass
with respect to the MRO of C: obviously, this is ``object.__new__``, since

  >>> print MRO(C)
  MRO of C:
    0 - C(B)[M]
    1 - B(object)
    2 - object()

This allows to create an instance of 'C' in this way:

  >>> super(B, C).__new__(C) 
  <__main__.C object at 0x4018750c>

It is interesting to notice that this would not work in Python 2.2,
due to a bug in the implementation of ``super``, therefore do not
try this trick with older version of Python. 

Notice that everything works 
only because ``B`` inherits the ``object.__new__`` staticmethod that 
is cooperative and it turns out that it calls ``type.__new__``. However, 
if I give to 'B' a non-cooperative method

  >>> B.__new__=staticmethod(lambda cls,*args: object.__new__(cls))

things do not work:

  >>> M('D',(),{}) #error
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "<stdin>", line 1, in <lambda>
  TypeError: object.__new__(M) is not safe, use type.__new__()

A cooperative method would solve the problem:

  >>> B.__new__=staticmethod(lambda m,*args: super(B,m).__new__(m,*args))
  >>> M('D',(),{}) # calls B.__new__(M,'D',(),{})
  <class '__main__.D'>

Cooperation between classes and metaclasses is pretty tricky.
This is why autosuper is so difficult to get right.

Consider this example, with object and type instances of MetaSuper::

  class B(object):
      def __init__(self, *args):
          print "B.__init__"
          self.__super.__init__(*args)

  class M(B, type):
      def __init__(self, n, b, d):
          print "M.__init__"
          self.__super.__init__(n, b, d)
       
  class C(B):
      __metaclass__ = M
      def __init__(self):
          print "C.__init__"
          self.__super.__init__()
 
What happens here at C creation? The metaclass _MMetaSuper is generated,
with ancestors M, B, superobject, supertype, MetaSuper, safetype, type,
which calls M.__init_(C, )_ and then B.__init__(C) which calls
the *unbound* method superobject.__init__(C ..) and NOT the *bound* method
MetaSuper.__init__(C, ) which would be the "right" thing to do in this 
situation (but not in other situations). So C._C__super is NOT initialized :-(

Metamethods vs class methods
-------------------------------------------------------------------

Meta-methods, i.e. methods defined in
a metaclass. 

Python has already few built-in metamethods such as ``.mro()``,
 ``__subclass__()``, ``__delattr__`` and possibly others. 
Moreover ``__name__`` is an example of meta-descriptor.
These are methods of the metaclass 'type' and there of any of its 
sub-metaclasses.

  >>> dir(type)
  ['__base__', '__bases__', '__basicsize__', '__call__', '__class__', 
   '__cmp__', '__delattr__', '__dict__', '__dictoffset__', '__doc__', 
   '__flags__', '__getattribute__', '__hash__', '__init__', '__itemsize__', 
   '__module__', '__mro__', '__name__', '__new__', '__reduce__', '__repr__', 
   '__setattr__', '__str__', '__subclasses__', '__weakrefoffset__', 'mro']


  >>> print type.mro.__doc__
  mro() -> list
  return a type's method resolution order
  >>> print type.__subclasses__.__doc__
  __subclasses__() -> list of immediate subclasses

  >>> class A(object): pass
  >>> class B(A): pass
  >>> B.mro()
  [<class '__main__.B'>, <class '__main__.A'>, <type 'object'>]
  >>> A.__subclasses__()
  [<class '__main__.B'>]

Notice that ``mro()`` and ``__subclasses__`` are not retrieved by ``dir``.

Let me constrast metamethods with the more traditional classmethods.
In many senses, the to concepts are akin:

  >>> class M(type): 
  ...    "Metaclass with a (meta)method mm"
  ...    def mm(cls): return cls
  >>> D=M('D',(),{'cm':classmethod(lambda cls: cls)}) 
  >>> # instance of M with a classmethod cm
  >>> D.mm # the metamethod
  <bound method M.mm of <class '__main__.C'>>
  >>> D.cm # the classmethod
  <unbound method D.<lambda>>

Notice the similarities between the classmethod and the metamethod:

  >>> D.mm.im_self, D.cm.im_self # the same
  (<class '__main__.D'>, <class '__main__.D'>)
  >>> D.mm.im_class, D.cm.im_class # still the same
  (<class '__main__.M'>, <class '__main__.M'>)

There are no surprises for ``im_func``:

  >>> D.mm.im_func, D.cm.im_func
  (<function mm at 0x402c272c>, <function <lambda> at 0x402c280c>)

Nevertheless, there are differences: metamethods are not bounded to
instances of the class 

  >>> D().cm() # the classmethod works fine
  <class '__main__.D'>
  >>> D().mm() # the metamethod does not: error
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
  AttributeError: 'D' object has no attribute 'mm'

and they are not retrieved by ``dir``:

  >>> from oopp import *
  >>> attributes(D).keys() # mm is not retrieved, only cm
  ['cm']

  >>> cm.__get__('whatever') #under Python 2.2.0 would give a serious error
  Segmentation fault
  >>> cm.__get__(None) #under Python 2.3 there is no error
  <bound method type.<lambda> of <type 'NoneType'>>

Moreover metamethods behaves differently with respect to multiple
inheritance. If a class A define a classmethod cA and a class B
defines a classmethod cB, then the class C(A,B) inherits both the
classmethods cA and cB. In the case of metamethods defined in M_A
and M_B, the same is true only if one resolves the meta-type
conflict by hand, by generating the metaclass M_C(M_A,M_B). In this
sense, classmethods are simpler to use than metamethods.