SlideShare ist ein Scribd-Unternehmen logo
1 von 81
Downloaden Sie, um offline zu lesen
Metaclass Programming in Python
                                     Advanced OO concepts


                                     Juan Manuel Gimeno Illa
                                       jmgimeno@diei.udl.cat

                                         December 2008




J.M.Gimeno (jmgimeno@diei.udl.cat)           Metaclasses       December 2008   1 / 21
This is dangerous, so don’t do it at home :-)



        [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 (c.l.p post 2002-12-22)




J.M.Gimeno (jmgimeno@diei.udl.cat)   Metaclasses              December 2008   2 / 21
Outline


 1   Basic Concepts

 2   How classes are created
       Inside class statement
       Metaclass Programming
       Metaclass Conflicts

 3   More Examples

 4   Concluding Remarks




J.M.Gimeno (jmgimeno@diei.udl.cat)   Metaclasses   December 2008   3 / 21
Basic Concepts


Objects and Classes
        Classes are templates used to create objects
               that share structure (attributes) and behaviour (methods)
               but have different state (attributes’ values)
        For object obj, type(obj) is the class or type of obj
        For object obj, type(type(obj)) is the metaclass or metatype of
        obj
        (Sometimes type(type(obj)) is referred as the metaclass of
        type(obj) but this is incorrect)
        The same way that classes shape objects, metaclasses shape classes.
        For instance, in Python, the difference between new and old classes
        resides in the metaclass used to create the classes
        (Note that the difference in metaclass can affect the objects of the
        classes. For instance, instances of new-style classes behave differently
        than those of old-style ones)

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses          December 2008   4 / 21
Basic Concepts


Objects and Classes
        Classes are templates used to create objects
               that share structure (attributes) and behaviour (methods)
               but have different state (attributes’ values)
        For object obj, type(obj) is the class or type of obj
        For object obj, type(type(obj)) is the metaclass or metatype of
        obj
        (Sometimes type(type(obj)) is referred as the metaclass of
        type(obj) but this is incorrect)
        The same way that classes shape objects, metaclasses shape classes.
        For instance, in Python, the difference between new and old classes
        resides in the metaclass used to create the classes
        (Note that the difference in metaclass can affect the objects of the
        classes. For instance, instances of new-style classes behave differently
        than those of old-style ones)

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses          December 2008   4 / 21
Basic Concepts


Objects and Classes
        Classes are templates used to create objects
               that share structure (attributes) and behaviour (methods)
               but have different state (attributes’ values)
        For object obj, type(obj) is the class or type of obj
        For object obj, type(type(obj)) is the metaclass or metatype of
        obj
        (Sometimes type(type(obj)) is referred as the metaclass of
        type(obj) but this is incorrect)
        The same way that classes shape objects, metaclasses shape classes.
        For instance, in Python, the difference between new and old classes
        resides in the metaclass used to create the classes
        (Note that the difference in metaclass can affect the objects of the
        classes. For instance, instances of new-style classes behave differently
        than those of old-style ones)

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses          December 2008   4 / 21
Basic Concepts


Objects and Classes
        Classes are templates used to create objects
               that share structure (attributes) and behaviour (methods)
               but have different state (attributes’ values)
        For object obj, type(obj) is the class or type of obj
        For object obj, type(type(obj)) is the metaclass or metatype of
        obj
        (Sometimes type(type(obj)) is referred as the metaclass of
        type(obj) but this is incorrect)
        The same way that classes shape objects, metaclasses shape classes.
        For instance, in Python, the difference between new and old classes
        resides in the metaclass used to create the classes
        (Note that the difference in metaclass can affect the objects of the
        classes. For instance, instances of new-style classes behave differently
        than those of old-style ones)

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses          December 2008   4 / 21
Basic Concepts


Objects and Classes
        Classes are templates used to create objects
               that share structure (attributes) and behaviour (methods)
               but have different state (attributes’ values)
        For object obj, type(obj) is the class or type of obj
        For object obj, type(type(obj)) is the metaclass or metatype of
        obj
        (Sometimes type(type(obj)) is referred as the metaclass of
        type(obj) but this is incorrect)
        The same way that classes shape objects, metaclasses shape classes.
        For instance, in Python, the difference between new and old classes
        resides in the metaclass used to create the classes
        (Note that the difference in metaclass can affect the objects of the
        classes. For instance, instances of new-style classes behave differently
        than those of old-style ones)

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses          December 2008   4 / 21
Basic Concepts


Objects and Classes
        Classes are templates used to create objects
               that share structure (attributes) and behaviour (methods)
               but have different state (attributes’ values)
        For object obj, type(obj) is the class or type of obj
        For object obj, type(type(obj)) is the metaclass or metatype of
        obj
        (Sometimes type(type(obj)) is referred as the metaclass of
        type(obj) but this is incorrect)
        The same way that classes shape objects, metaclasses shape classes.
        For instance, in Python, the difference between new and old classes
        resides in the metaclass used to create the classes
        (Note that the difference in metaclass can affect the objects of the
        classes. For instance, instances of new-style classes behave differently
        than those of old-style ones)

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses          December 2008   4 / 21
Basic Concepts


Objects and Classes
        Classes are templates used to create objects
               that share structure (attributes) and behaviour (methods)
               but have different state (attributes’ values)
        For object obj, type(obj) is the class or type of obj
        For object obj, type(type(obj)) is the metaclass or metatype of
        obj
        (Sometimes type(type(obj)) is referred as the metaclass of
        type(obj) but this is incorrect)
        The same way that classes shape objects, metaclasses shape classes.
        For instance, in Python, the difference between new and old classes
        resides in the metaclass used to create the classes
        (Note that the difference in metaclass can affect the objects of the
        classes. For instance, instances of new-style classes behave differently
        than those of old-style ones)

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses          December 2008   4 / 21
Basic Concepts


Objects and Classes
        Classes are templates used to create objects
               that share structure (attributes) and behaviour (methods)
               but have different state (attributes’ values)
        For object obj, type(obj) is the class or type of obj
        For object obj, type(type(obj)) is the metaclass or metatype of
        obj
        (Sometimes type(type(obj)) is referred as the metaclass of
        type(obj) but this is incorrect)
        The same way that classes shape objects, metaclasses shape classes.
        For instance, in Python, the difference between new and old classes
        resides in the metaclass used to create the classes
        (Note that the difference in metaclass can affect the objects of the
        classes. For instance, instances of new-style classes behave differently
        than those of old-style ones)

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses          December 2008   4 / 21
Basic Concepts


Objects and Classes
        Classes are templates used to create objects
               that share structure (attributes) and behaviour (methods)
               but have different state (attributes’ values)
        For object obj, type(obj) is the class or type of obj
        For object obj, type(type(obj)) is the metaclass or metatype of
        obj
        (Sometimes type(type(obj)) is referred as the metaclass of
        type(obj) but this is incorrect)
        The same way that classes shape objects, metaclasses shape classes.
        For instance, in Python, the difference between new and old classes
        resides in the metaclass used to create the classes
        (Note that the difference in metaclass can affect the objects of the
        classes. For instance, instances of new-style classes behave differently
        than those of old-style ones)

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses          December 2008   4 / 21
Basic Concepts


New and Old Classes

>>> class New(object): pass
...
>>> class Old: pass
...                                                          Differences in new and
>>> n = New()                                                old style objects (for
>>> o = Old()                                                instance, the mro of
>>> type(n)                                                  attributes) . . .
<class ’ main .New’>
>>> type(o)                                                  . . . are due to the
<type ’instance’>                                            different metaclasses
>>> type(New)                                                they have
<type ’type’>
>>> type(Old)
<type ’classobj’>

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses           December 2008   5 / 21
Basic Concepts


New and Old Classes

>>> class New(object): pass
...
>>> class Old: pass
...                                                          Differences in new and
>>> n = New()                                                old style objects (for
>>> o = Old()                                                instance, the mro of
>>> type(n)                                                  attributes) . . .
<class ’ main .New’>
>>> type(o)                                                  . . . are due to the
<type ’instance’>                                            different metaclasses
>>> type(New)                                                they have
<type ’type’>
>>> type(Old)
<type ’classobj’>

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses           December 2008   5 / 21
Basic Concepts


New and Old Classes

>>> class New(object): pass
...
>>> class Old: pass
...                                                          Differences in new and
>>> n = New()                                                old style objects (for
>>> o = Old()                                                instance, the mro of
>>> type(n)                                                  attributes) . . .
<class ’ main .New’>
>>> type(o)                                                  . . . are due to the
<type ’instance’>                                            different metaclasses
>>> type(New)                                                they have
<type ’type’>
>>> type(Old)
<type ’classobj’>

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses           December 2008   5 / 21
Basic Concepts


New and Old Classes

>>> class New(object): pass
...
>>> class Old: pass
...                                                          Differences in new and
>>> n = New()                                                old style objects (for
>>> o = Old()                                                instance, the mro of
>>> type(n)                                                  attributes) . . .
<class ’ main .New’>
>>> type(o)                                                  . . . are due to the
<type ’instance’>                                            different metaclasses
>>> type(New)                                                they have
<type ’type’>
>>> type(Old)
<type ’classobj’>

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses           December 2008   5 / 21
Basic Concepts


New and Old Classes

>>> class New(object): pass
...
>>> class Old: pass
...                                                          Differences in new and
>>> n = New()                                                old style objects (for
>>> o = Old()                                                instance, the mro of
>>> type(n)                                                  attributes) . . .
<class ’ main .New’>
>>> type(o)                                                  . . . are due to the
<type ’instance’>                                            different metaclasses
>>> type(New)                                                they have
<type ’type’>
>>> type(Old)
<type ’classobj’>

J.M.Gimeno (jmgimeno@diei.udl.cat)             Metaclasses           December 2008   5 / 21
How classes are created   Inside class statement


The built-in type
        type(name, bases, attribs)(a.k.a types.TypeType) creates a
        new-style class object
               name is a string containing the name of the class
                      (C. name )
               bases is a tuple containing the base classes for the new class
                      (C. bases )
             attribs is a dictionary pairing the attribute’s names with
                      their corresponding values
        So the usual class statement (when dealing with new-style classes)

 class Class(base1, base2, ...):
     statements
        calls type with parameters ‘‘Class’’, (base1, base2, ...) and
        a dictionary containing the bindings created by the execution of the
        statements.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   6 / 21
How classes are created   Inside class statement


The built-in type
        type(name, bases, attribs)(a.k.a types.TypeType) creates a
        new-style class object
               name is a string containing the name of the class
                      (C. name )
               bases is a tuple containing the base classes for the new class
                      (C. bases )
             attribs is a dictionary pairing the attribute’s names with
                      their corresponding values
        So the usual class statement (when dealing with new-style classes)

 class Class(base1, base2, ...):
     statements
        calls type with parameters ‘‘Class’’, (base1, base2, ...) and
        a dictionary containing the bindings created by the execution of the
        statements.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   6 / 21
How classes are created   Inside class statement


The built-in type
        type(name, bases, attribs)(a.k.a types.TypeType) creates a
        new-style class object
               name is a string containing the name of the class
                      (C. name )
               bases is a tuple containing the base classes for the new class
                      (C. bases )
             attribs is a dictionary pairing the attribute’s names with
                      their corresponding values
        So the usual class statement (when dealing with new-style classes)

 class Class(base1, base2, ...):
     statements
        calls type with parameters ‘‘Class’’, (base1, base2, ...) and
        a dictionary containing the bindings created by the execution of the
        statements.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   6 / 21
How classes are created   Inside class statement


The built-in type
        type(name, bases, attribs)(a.k.a types.TypeType) creates a
        new-style class object
               name is a string containing the name of the class
                      (C. name )
               bases is a tuple containing the base classes for the new class
                      (C. bases )
             attribs is a dictionary pairing the attribute’s names with
                      their corresponding values
        So the usual class statement (when dealing with new-style classes)

 class Class(base1, base2, ...):
     statements
        calls type with parameters ‘‘Class’’, (base1, base2, ...) and
        a dictionary containing the bindings created by the execution of the
        statements.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   6 / 21
How classes are created   Inside class statement


The built-in type
        type(name, bases, attribs)(a.k.a types.TypeType) creates a
        new-style class object
               name is a string containing the name of the class
                      (C. name )
               bases is a tuple containing the base classes for the new class
                      (C. bases )
             attribs is a dictionary pairing the attribute’s names with
                      their corresponding values
        So the usual class statement (when dealing with new-style classes)

 class Class(base1, base2, ...):
     statements
        calls type with parameters ‘‘Class’’, (base1, base2, ...) and
        a dictionary containing the bindings created by the execution of the
        statements.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   6 / 21
How classes are created   Inside class statement


Inside the class statement
       When one defines a new-style class:

 >>> class Class1(object):
 ... attrib = 1
 ... def __init__(self, n):
 ...         self.n = n
       One actually executes:

 >>> class_name = quot;Class1quot;
 >>> class_bases = (object,)
 >>> class_dict = {}
 >>> class_body = quot;quot;quot;
 attrib = 1
 def __init__(self, n):
     self.n = n
 quot;quot;quot;
 >>> exec class_body in globals(), class_dict
 >>> locals()[class_name] = type(class_name, class_bases, class_dict)

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   7 / 21
How classes are created   Inside class statement


Inside the class statement
       When one defines a new-style class:

 >>> class Class1(object):
 ... attrib = 1
 ... def __init__(self, n):
 ...         self.n = n
       One actually executes:

 >>> class_name = quot;Class1quot;
 >>> class_bases = (object,)
 >>> class_dict = {}
 >>> class_body = quot;quot;quot;
 attrib = 1
 def __init__(self, n):
     self.n = n
 quot;quot;quot;
 >>> exec class_body in globals(), class_dict
 >>> locals()[class_name] = type(class_name, class_bases, class_dict)

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   7 / 21
How classes are created   Inside class statement


Inside the class statement
       When one defines a new-style class:

 >>> class Class1(object):
 ... attrib = 1
 ... def __init__(self, n):
 ...         self.n = n
       One actually executes:

 >>> class_name = quot;Class1quot;
 >>> class_bases = (object,)
 >>> class_dict = {}
 >>> class_body = quot;quot;quot;
 attrib = 1
 def __init__(self, n):
     self.n = n
 quot;quot;quot;
 >>> exec class_body in globals(), class_dict
 >>> locals()[class_name] = type(class_name, class_bases, class_dict)

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   7 / 21
How classes are created   Inside class statement


Inside the class statement
       When one defines a new-style class:

 >>> class Class1(object):
 ... attrib = 1
 ... def __init__(self, n):
 ...         self.n = n
       One actually executes:

 >>> class_name = quot;Class1quot;
 >>> class_bases = (object,)
 >>> class_dict = {}
 >>> class_body = quot;quot;quot;
 attrib = 1
 def __init__(self, n):
     self.n = n
 quot;quot;quot;
 >>> exec class_body in globals(), class_dict
 >>> locals()[class_name] = type(class_name, class_bases, class_dict)

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   7 / 21
How classes are created   Inside class statement


The full truth of the class statement
 To execute a class statement:
    1    Python first collects the class name in a string n, the base classes into
         a tuple t and executes the body in dictionary d
    2    Then determines the metaclass to use for the new class object C
           1   When metaclass is a key in d, then M = d[’ metaclass ’]
           2   When t is nonempty, then M is the leafmost1 metaclass among all the
               metaclasses of C’s bases that are not old-style classes
           3   If the current module has a global variable metaclass , then M is
               the value of this variable
           4   Failing all of these, M defaults to types.ClassType, that is, an
               old-style class is created
    3    Finally, C = M(n, t, d)

     1
      If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower
 bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing
 this metatype conflict.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   8 / 21
How classes are created   Inside class statement


The full truth of the class statement
 To execute a class statement:
    1    Python first collects the class name in a string n, the base classes into
         a tuple t and executes the body in dictionary d
    2    Then determines the metaclass to use for the new class object C
           1   When metaclass is a key in d, then M = d[’ metaclass ’]
           2   When t is nonempty, then M is the leafmost1 metaclass among all the
               metaclasses of C’s bases that are not old-style classes
           3   If the current module has a global variable metaclass , then M is
               the value of this variable
           4   Failing all of these, M defaults to types.ClassType, that is, an
               old-style class is created
    3    Finally, C = M(n, t, d)

     1
      If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower
 bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing
 this metatype conflict.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   8 / 21
How classes are created   Inside class statement


The full truth of the class statement
 To execute a class statement:
    1    Python first collects the class name in a string n, the base classes into
         a tuple t and executes the body in dictionary d
    2    Then determines the metaclass to use for the new class object C
           1   When metaclass is a key in d, then M = d[’ metaclass ’]
           2   When t is nonempty, then M is the leafmost1 metaclass among all the
               metaclasses of C’s bases that are not old-style classes
           3   If the current module has a global variable metaclass , then M is
               the value of this variable
           4   Failing all of these, M defaults to types.ClassType, that is, an
               old-style class is created
    3    Finally, C = M(n, t, d)

     1
      If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower
 bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing
 this metatype conflict.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   8 / 21
How classes are created   Inside class statement


The full truth of the class statement
 To execute a class statement:
    1    Python first collects the class name in a string n, the base classes into
         a tuple t and executes the body in dictionary d
    2    Then determines the metaclass to use for the new class object C
           1   When metaclass is a key in d, then M = d[’ metaclass ’]
           2   When t is nonempty, then M is the leafmost1 metaclass among all the
               metaclasses of C’s bases that are not old-style classes
           3   If the current module has a global variable metaclass , then M is
               the value of this variable
           4   Failing all of these, M defaults to types.ClassType, that is, an
               old-style class is created
    3    Finally, C = M(n, t, d)

     1
      If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower
 bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing
 this metatype conflict.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   8 / 21
How classes are created   Inside class statement


The full truth of the class statement
 To execute a class statement:
    1    Python first collects the class name in a string n, the base classes into
         a tuple t and executes the body in dictionary d
    2    Then determines the metaclass to use for the new class object C
           1   When metaclass is a key in d, then M = d[’ metaclass ’]
           2   When t is nonempty, then M is the leafmost1 metaclass among all the
               metaclasses of C’s bases that are not old-style classes
           3   If the current module has a global variable metaclass , then M is
               the value of this variable
           4   Failing all of these, M defaults to types.ClassType, that is, an
               old-style class is created
    3    Finally, C = M(n, t, d)

     1
      If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower
 bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing
 this metatype conflict.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   8 / 21
How classes are created   Inside class statement


The full truth of the class statement
 To execute a class statement:
    1    Python first collects the class name in a string n, the base classes into
         a tuple t and executes the body in dictionary d
    2    Then determines the metaclass to use for the new class object C
           1   When metaclass is a key in d, then M = d[’ metaclass ’]
           2   When t is nonempty, then M is the leafmost1 metaclass among all the
               metaclasses of C’s bases that are not old-style classes
           3   If the current module has a global variable metaclass , then M is
               the value of this variable
           4   Failing all of these, M defaults to types.ClassType, that is, an
               old-style class is created
    3    Finally, C = M(n, t, d)

     1
      If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower
 bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing
 this metatype conflict.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   8 / 21
How classes are created   Inside class statement


The full truth of the class statement
 To execute a class statement:
    1    Python first collects the class name in a string n, the base classes into
         a tuple t and executes the body in dictionary d
    2    Then determines the metaclass to use for the new class object C
           1   When metaclass is a key in d, then M = d[’ metaclass ’]
           2   When t is nonempty, then M is the leafmost1 metaclass among all the
               metaclasses of C’s bases that are not old-style classes
           3   If the current module has a global variable metaclass , then M is
               the value of this variable
           4   Failing all of these, M defaults to types.ClassType, that is, an
               old-style class is created
    3    Finally, C = M(n, t, d)

     1
      If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower
 bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing
 this metatype conflict.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   8 / 21
How classes are created   Inside class statement


The full truth of the class statement
 To execute a class statement:
    1    Python first collects the class name in a string n, the base classes into
         a tuple t and executes the body in dictionary d
    2    Then determines the metaclass to use for the new class object C
           1   When metaclass is a key in d, then M = d[’ metaclass ’]
           2   When t is nonempty, then M is the leafmost1 metaclass among all the
               metaclasses of C’s bases that are not old-style classes
           3   If the current module has a global variable metaclass , then M is
               the value of this variable
           4   Failing all of these, M defaults to types.ClassType, that is, an
               old-style class is created
    3    Finally, C = M(n, t, d)

     1
      If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower
 bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing
 this metatype conflict.
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                     December 2008   8 / 21
How classes are created   Metaclass Programming


A very simple metaclass
       Redefining method repr in class changes the way python show its
       instances
       So to change the way python shows a class, we redefine repr in the
       metaclass
 >>> class MetaPretty(type):
 ...      def __repr__(cls):
 ...          return quot;I’m the class %squot; % cls.__name__
 ...
 >>> class Ugly: pass
 >>> Ugly
 <class ’__main__.Ugly’>
 >>> class Pretty(object):
 ...      __metaclass__ = MetaPretty
 >>> Pretty
 I’m the class Pretty

       Metaclass programming is easier than you thought !!!

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                    December 2008   9 / 21
How classes are created   Metaclass Programming


A very simple metaclass
       Redefining method repr in class changes the way python show its
       instances
       So to change the way python shows a class, we redefine repr in the
       metaclass
 >>> class MetaPretty(type):
 ...      def __repr__(cls):
 ...          return quot;I’m the class %squot; % cls.__name__
 ...
 >>> class Ugly: pass
 >>> Ugly
 <class ’__main__.Ugly’>
 >>> class Pretty(object):
 ...      __metaclass__ = MetaPretty
 >>> Pretty
 I’m the class Pretty

       Metaclass programming is easier than you thought !!!

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                    December 2008   9 / 21
How classes are created   Metaclass Programming


A very simple metaclass
       Redefining method repr in class changes the way python show its
       instances
       So to change the way python shows a class, we redefine repr in the
       metaclass
 >>> class MetaPretty(type):
 ...      def __repr__(cls):
 ...          return quot;I’m the class %squot; % cls.__name__
 ...
 >>> class Ugly: pass
 >>> Ugly
 <class ’__main__.Ugly’>
 >>> class Pretty(object):
 ...      __metaclass__ = MetaPretty
 >>> Pretty
 I’m the class Pretty

       Metaclass programming is easier than you thought !!!

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                    December 2008   9 / 21
How classes are created   Metaclass Programming


A very simple metaclass
       Redefining method repr in class changes the way python show its
       instances
       So to change the way python shows a class, we redefine repr in the
       metaclass
 >>> class MetaPretty(type):
 ...      def __repr__(cls):
 ...          return quot;I’m the class %squot; % cls.__name__
 ...
 >>> class Ugly: pass
 >>> Ugly
 <class ’__main__.Ugly’>
 >>> class Pretty(object):
 ...      __metaclass__ = MetaPretty
 >>> Pretty
 I’m the class Pretty

       Metaclass programming is easier than you thought !!!

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                    December 2008   9 / 21
How classes are created   Metaclass Programming


Automatic property creation I
       We don’t want to tell python the properties defined in a class if there are
       methods in the class that evidently want a property defined !!!
       We implement it redefining init

 class MetaAutoProp(type):
     def __init__(cls, name, bases, dict):
         super(MetaAutoProp, cls).__init__(name, bases, dict)
         props = set(name[5:] for name in dict.iterkeys()
                              if name.startswith(quot;_get_quot;) or 
                              name.startswith(quot;_set_quot;))
         for name in props:
             fget = getattr(cls, quot;_get_%squot; % name, None)
             fset = getattr(cls, quot;_set_%squot; % name, None)
             setattr(cls, name, property(fget, fset))
 class AutoProp(object): __metaclass__ = MetaAutoProp
 class UseX(AutoProp):
     def __init__(self): self.__x = 0
     def _get_x(self): return self.__x
     def _set_x(self, x): self.__x = x

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                    December 2008   10 / 21
How classes are created   Metaclass Programming


Automatic property creation I
       We don’t want to tell python the properties defined in a class if there are
       methods in the class that evidently want a property defined !!!
       We implement it redefining init

 class MetaAutoProp(type):
     def __init__(cls, name, bases, dict):
         super(MetaAutoProp, cls).__init__(name, bases, dict)
         props = set(name[5:] for name in dict.iterkeys()
                              if name.startswith(quot;_get_quot;) or 
                              name.startswith(quot;_set_quot;))
         for name in props:
             fget = getattr(cls, quot;_get_%squot; % name, None)
             fset = getattr(cls, quot;_set_%squot; % name, None)
             setattr(cls, name, property(fget, fset))
 class AutoProp(object): __metaclass__ = MetaAutoProp
 class UseX(AutoProp):
     def __init__(self): self.__x = 0
     def _get_x(self): return self.__x
     def _set_x(self, x): self.__x = x

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                    December 2008   10 / 21
How classes are created   Metaclass Programming


Automatic property creation I
       We don’t want to tell python the properties defined in a class if there are
       methods in the class that evidently want a property defined !!!
       We implement it redefining init

 class MetaAutoProp(type):
     def __init__(cls, name, bases, dict):
         super(MetaAutoProp, cls).__init__(name, bases, dict)
         props = set(name[5:] for name in dict.iterkeys()
                              if name.startswith(quot;_get_quot;) or 
                              name.startswith(quot;_set_quot;))
         for name in props:
             fget = getattr(cls, quot;_get_%squot; % name, None)
             fset = getattr(cls, quot;_set_%squot; % name, None)
             setattr(cls, name, property(fget, fset))
 class AutoProp(object): __metaclass__ = MetaAutoProp
 class UseX(AutoProp):
     def __init__(self): self.__x = 0
     def _get_x(self): return self.__x
     def _set_x(self, x): self.__x = x

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                    December 2008   10 / 21
How classes are created   Metaclass Programming


Automatic property creation II
       The same as before but this time the implementation redefines               new

 class MetaAutoProp(type):
     def __new__(mcl, classname, bases, dict):
         props = set(name[5:] for name in dict.iterkeys()
                              if name.startswith(quot;_get_quot;) or 
                                 name.startswith(quot;_set_quot;))
         for name in props:
             fget = dict.get(quot;_get_%squot; % name)
             fset = dict.get(quot;_set_%squot; % name)
             dict[name] = property(fget, fset)
         super_ = super(MetaAutoProp, mcl)
         return super_.__new__(mcl, classname, bases, dict)
 class AutoProp(object): __metaclass__ = MetaAutoProp
 class UseX(AutoProp):
     def __init__(self): self.__x = 0
     def _get_x(self): return self.__x
     def _set_x(self, x): self.__x = x

       Deciding which way to go is not clearly defined
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                    December 2008   11 / 21
How classes are created   Metaclass Programming


Automatic property creation II
       The same as before but this time the implementation redefines               new

 class MetaAutoProp(type):
     def __new__(mcl, classname, bases, dict):
         props = set(name[5:] for name in dict.iterkeys()
                              if name.startswith(quot;_get_quot;) or 
                                 name.startswith(quot;_set_quot;))
         for name in props:
             fget = dict.get(quot;_get_%squot; % name)
             fset = dict.get(quot;_set_%squot; % name)
             dict[name] = property(fget, fset)
         super_ = super(MetaAutoProp, mcl)
         return super_.__new__(mcl, classname, bases, dict)
 class AutoProp(object): __metaclass__ = MetaAutoProp
 class UseX(AutoProp):
     def __init__(self): self.__x = 0
     def _get_x(self): return self.__x
     def _set_x(self, x): self.__x = x

       Deciding which way to go is not clearly defined
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                    December 2008   11 / 21
How classes are created   Metaclass Programming


Automatic property creation II
       The same as before but this time the implementation redefines               new

 class MetaAutoProp(type):
     def __new__(mcl, classname, bases, dict):
         props = set(name[5:] for name in dict.iterkeys()
                              if name.startswith(quot;_get_quot;) or 
                                 name.startswith(quot;_set_quot;))
         for name in props:
             fget = dict.get(quot;_get_%squot; % name)
             fset = dict.get(quot;_set_%squot; % name)
             dict[name] = property(fget, fset)
         super_ = super(MetaAutoProp, mcl)
         return super_.__new__(mcl, classname, bases, dict)
 class AutoProp(object): __metaclass__ = MetaAutoProp
 class UseX(AutoProp):
     def __init__(self): self.__x = 0
     def _get_x(self): return self.__x
     def _set_x(self, x): self.__x = x

       Deciding which way to go is not clearly defined
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                    December 2008   11 / 21
How classes are created   Metaclass Programming


Automatic Initialization of Instance Attributes
 import inspect
 class auto_attr(object):
     def __init__(self, factory, *args, **kwargs):
         self.creation_data = (factory, args, kwargs)
 def is_auto_attr(attr):
     return isinstance(attr, auto_attr)
 class MetaAutoAttr(type):
     def __call__(cls, *args, **kwargs):
         obj = super(MetaAutoAttr, cls).__call__(*args, **kwargs)
         for attr, value in inspect.getmembers(cls, is_auto_attr):
             factory, a, k = value.creation_data
             setattr(obj, attr, factory(*a, **k))
         return obj
 class AutoAttr(object): __metaclass__ = MetaAutoAttr
 class Recorder(AutoAttr):
     count = 0 # is immutable so no shared among instances
     events = auto_attr(list)
     def record(self, event):
         self.count += 1
         self.events.append((self.count, event))

J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                    December 2008   12 / 21
How classes are created   Metaclass Conflicts


But, sometimes, conflicts happen
       Imagine one wants a class with both behaviours. If one tries:

 from autoprop import AutoProp
 from autoattr import AutoAttr, auto_attr
 class Both(AutoProp, AutoAttr):
     __x = auto_attr(list)
     def _get_x(self): return self.__x
     def _set_x(self, v): self.__x = v

       One gets:

 TypeError: Error when calling the metaclass bases
       metaclass conflict: the metaclass of a derived class must be a (non-strict)
 subclass of the metaclasses of all its bases
       The problem is that python needs to find a metaclass that brings both
       behaviours at the same time
       (This is the application of the Liskov Substitution Principle applied to
       metaclasses)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   13 / 21
How classes are created   Metaclass Conflicts


But, sometimes, conflicts happen
       Imagine one wants a class with both behaviours. If one tries:

 from autoprop import AutoProp
 from autoattr import AutoAttr, auto_attr
 class Both(AutoProp, AutoAttr):
     __x = auto_attr(list)
     def _get_x(self): return self.__x
     def _set_x(self, v): self.__x = v

       One gets:

 TypeError: Error when calling the metaclass bases
       metaclass conflict: the metaclass of a derived class must be a (non-strict)
 subclass of the metaclasses of all its bases
       The problem is that python needs to find a metaclass that brings both
       behaviours at the same time
       (This is the application of the Liskov Substitution Principle applied to
       metaclasses)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   13 / 21
How classes are created   Metaclass Conflicts


But, sometimes, conflicts happen
       Imagine one wants a class with both behaviours. If one tries:

 from autoprop import AutoProp
 from autoattr import AutoAttr, auto_attr
 class Both(AutoProp, AutoAttr):
     __x = auto_attr(list)
     def _get_x(self): return self.__x
     def _set_x(self, v): self.__x = v

       One gets:

 TypeError: Error when calling the metaclass bases
       metaclass conflict: the metaclass of a derived class must be a (non-strict)
 subclass of the metaclasses of all its bases
       The problem is that python needs to find a metaclass that brings both
       behaviours at the same time
       (This is the application of the Liskov Substitution Principle applied to
       metaclasses)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   13 / 21
How classes are created   Metaclass Conflicts


But, sometimes, conflicts happen
       Imagine one wants a class with both behaviours. If one tries:

 from autoprop import AutoProp
 from autoattr import AutoAttr, auto_attr
 class Both(AutoProp, AutoAttr):
     __x = auto_attr(list)
     def _get_x(self): return self.__x
     def _set_x(self, v): self.__x = v

       One gets:

 TypeError: Error when calling the metaclass bases
       metaclass conflict: the metaclass of a derived class must be a (non-strict)
 subclass of the metaclasses of all its bases
       The problem is that python needs to find a metaclass that brings both
       behaviours at the same time
       (This is the application of the Liskov Substitution Principle applied to
       metaclasses)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   13 / 21
How classes are created   Metaclass Conflicts


But, sometimes, conflicts happen
       Imagine one wants a class with both behaviours. If one tries:

 from autoprop import AutoProp
 from autoattr import AutoAttr, auto_attr
 class Both(AutoProp, AutoAttr):
     __x = auto_attr(list)
     def _get_x(self): return self.__x
     def _set_x(self, v): self.__x = v

       One gets:

 TypeError: Error when calling the metaclass bases
       metaclass conflict: the metaclass of a derived class must be a (non-strict)
 subclass of the metaclasses of all its bases
       The problem is that python needs to find a metaclass that brings both
       behaviours at the same time
       (This is the application of the Liskov Substitution Principle applied to
       metaclasses)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   13 / 21
How classes are created   Metaclass Conflicts


But, sometimes, conflicts happen
       Imagine one wants a class with both behaviours. If one tries:

 from autoprop import AutoProp
 from autoattr import AutoAttr, auto_attr
 class Both(AutoProp, AutoAttr):
     __x = auto_attr(list)
     def _get_x(self): return self.__x
     def _set_x(self, v): self.__x = v

       One gets:

 TypeError: Error when calling the metaclass bases
       metaclass conflict: the metaclass of a derived class must be a (non-strict)
 subclass of the metaclasses of all its bases
       The problem is that python needs to find a metaclass that brings both
       behaviours at the same time
       (This is the application of the Liskov Substitution Principle applied to
       metaclasses)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   13 / 21
How classes are created   Metaclass Conflicts


Solving the metaclass conflict
      To ensured it, the metaclass to use must be a subclass of all those of the
      bases of the class
      (Technically it must be minimal in the inheritance subgraph of the metaclasses
      of the bases considered as a lattice)
      Some languages create an on-the-fly this minimal metaclass if needed
      Python needs you to solve the problem , so:

 from autoprop import MetaAutoProp
 from autoattr import MetaAutoAttr, auto_attr
 class MetaBoth(MetaAutoAttr, MetaAutoProp): pass
 class Both(object):
     __metaclass__ = MetaBoth
     __x = auto_attr(list)
     def _get_x(self):
         return self.__x
     def _set_x(self, value):
         self.__x = value

      (A recipe exists in the Python Cookbook that solves this problem by defining
      a metaclass factory method which creates the appropriate metaclass when
      needed)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   14 / 21
How classes are created   Metaclass Conflicts


Solving the metaclass conflict
      To ensured it, the metaclass to use must be a subclass of all those of the
      bases of the class
      (Technically it must be minimal in the inheritance subgraph of the metaclasses
      of the bases considered as a lattice)
      Some languages create an on-the-fly this minimal metaclass if needed
      Python needs you to solve the problem , so:

 from autoprop import MetaAutoProp
 from autoattr import MetaAutoAttr, auto_attr
 class MetaBoth(MetaAutoAttr, MetaAutoProp): pass
 class Both(object):
     __metaclass__ = MetaBoth
     __x = auto_attr(list)
     def _get_x(self):
         return self.__x
     def _set_x(self, value):
         self.__x = value

      (A recipe exists in the Python Cookbook that solves this problem by defining
      a metaclass factory method which creates the appropriate metaclass when
      needed)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   14 / 21
How classes are created   Metaclass Conflicts


Solving the metaclass conflict
      To ensured it, the metaclass to use must be a subclass of all those of the
      bases of the class
      (Technically it must be minimal in the inheritance subgraph of the metaclasses
      of the bases considered as a lattice)
      Some languages create an on-the-fly this minimal metaclass if needed
      Python needs you to solve the problem , so:

 from autoprop import MetaAutoProp
 from autoattr import MetaAutoAttr, auto_attr
 class MetaBoth(MetaAutoAttr, MetaAutoProp): pass
 class Both(object):
     __metaclass__ = MetaBoth
     __x = auto_attr(list)
     def _get_x(self):
         return self.__x
     def _set_x(self, value):
         self.__x = value

      (A recipe exists in the Python Cookbook that solves this problem by defining
      a metaclass factory method which creates the appropriate metaclass when
      needed)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   14 / 21
How classes are created   Metaclass Conflicts


Solving the metaclass conflict
      To ensured it, the metaclass to use must be a subclass of all those of the
      bases of the class
      (Technically it must be minimal in the inheritance subgraph of the metaclasses
      of the bases considered as a lattice)
      Some languages create an on-the-fly this minimal metaclass if needed
      Python needs you to solve the problem , so:

 from autoprop import MetaAutoProp
 from autoattr import MetaAutoAttr, auto_attr
 class MetaBoth(MetaAutoAttr, MetaAutoProp): pass
 class Both(object):
     __metaclass__ = MetaBoth
     __x = auto_attr(list)
     def _get_x(self):
         return self.__x
     def _set_x(self, value):
         self.__x = value

      (A recipe exists in the Python Cookbook that solves this problem by defining
      a metaclass factory method which creates the appropriate metaclass when
      needed)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   14 / 21
How classes are created   Metaclass Conflicts


Solving the metaclass conflict
      To ensured it, the metaclass to use must be a subclass of all those of the
      bases of the class
      (Technically it must be minimal in the inheritance subgraph of the metaclasses
      of the bases considered as a lattice)
      Some languages create an on-the-fly this minimal metaclass if needed
      Python needs you to solve the problem , so:

 from autoprop import MetaAutoProp
 from autoattr import MetaAutoAttr, auto_attr
 class MetaBoth(MetaAutoAttr, MetaAutoProp): pass
 class Both(object):
     __metaclass__ = MetaBoth
     __x = auto_attr(list)
     def _get_x(self):
         return self.__x
     def _set_x(self, value):
         self.__x = value

      (A recipe exists in the Python Cookbook that solves this problem by defining
      a metaclass factory method which creates the appropriate metaclass when
      needed)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   14 / 21
How classes are created   Metaclass Conflicts


Solving the metaclass conflict
      To ensured it, the metaclass to use must be a subclass of all those of the
      bases of the class
      (Technically it must be minimal in the inheritance subgraph of the metaclasses
      of the bases considered as a lattice)
      Some languages create an on-the-fly this minimal metaclass if needed
      Python needs you to solve the problem , so:

 from autoprop import MetaAutoProp
 from autoattr import MetaAutoAttr, auto_attr
 class MetaBoth(MetaAutoAttr, MetaAutoProp): pass
 class Both(object):
     __metaclass__ = MetaBoth
     __x = auto_attr(list)
     def _get_x(self):
         return self.__x
     def _set_x(self, value):
         self.__x = value

      (A recipe exists in the Python Cookbook that solves this problem by defining
      a metaclass factory method which creates the appropriate metaclass when
      needed)
J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses                 December 2008   14 / 21
More Examples


Avoiding multiple initialization of Singletons
      The Singleton class that was presented before needed   init   to be
      idempotent. Changing its metaclass solves it:

 # Singleton classes are only init’ed once
 class Singleton(object):
     class __metaclass__(type):
         _initialized = set()
         def __call__(cls, *args, **kwargs):
             inits = Singleton.__metaclass__._initialized
             obj = cls.__new__(cls, *args, **kwargs)
             if isinstance(obj, cls) and 
                    cls not in inits:
                 inits.add(cls)
                 obj.__init__(*args, **kwargs)
             return obj
     _singletons = {}
     def __new__(cls, *args, **kwds):
         if cls not in cls._singletons:
             s = super(Singleton, cls)
             cls._singletons[cls] = 
                super(Singleton, cls).__new__(cls, *args, **kwds)
         return cls._singletons[cls]

J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses                   December 2008   15 / 21
More Examples


Avoiding multiple initialization of Singletons
      The Singleton class that was presented before needed   init   to be
      idempotent. Changing its metaclass solves it:

 # Singleton classes are only init’ed once
 class Singleton(object):
     class __metaclass__(type):
         _initialized = set()
         def __call__(cls, *args, **kwargs):
             inits = Singleton.__metaclass__._initialized
             obj = cls.__new__(cls, *args, **kwargs)
             if isinstance(obj, cls) and 
                    cls not in inits:
                 inits.add(cls)
                 obj.__init__(*args, **kwargs)
             return obj
     _singletons = {}
     def __new__(cls, *args, **kwds):
         if cls not in cls._singletons:
             s = super(Singleton, cls)
             cls._singletons[cls] = 
                super(Singleton, cls).__new__(cls, *args, **kwds)
         return cls._singletons[cls]

J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses                   December 2008   15 / 21
More Examples


Enforcing naming rules
       We don’t want classes with attributes that are not lowercase to be ever
       created !!!!
 class InvalidAttribName(TypeError): pass
 class MetaEnsureAttribNames(type):
     def __new__(mcl, name, bases, attrs):
         invalids = [attr for attr in attrs
                          if not attr.islower()]
         if invalids:
             msg = quot;Invalid Attributes: quot; + quot;, quot;.join(invalids)
             raise InvalidAttribName, msg
         super_ = super(MetaEnsureAttribNames, mcl)
         return super_.__new__(mcl, name, bases, attrs)
 class EnsureAttribNames(object):
     __metaclass__ = MetaEnsureAttribNames

       (You can experiment with different rules for methods, rules for class names,
       etc.)

J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses         December 2008   16 / 21
More Examples


Enforcing naming rules
       We don’t want classes with attributes that are not lowercase to be ever
       created !!!!
 class InvalidAttribName(TypeError): pass
 class MetaEnsureAttribNames(type):
     def __new__(mcl, name, bases, attrs):
         invalids = [attr for attr in attrs
                          if not attr.islower()]
         if invalids:
             msg = quot;Invalid Attributes: quot; + quot;, quot;.join(invalids)
             raise InvalidAttribName, msg
         super_ = super(MetaEnsureAttribNames, mcl)
         return super_.__new__(mcl, name, bases, attrs)
 class EnsureAttribNames(object):
     __metaclass__ = MetaEnsureAttribNames

       (You can experiment with different rules for methods, rules for class names,
       etc.)

J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses         December 2008   16 / 21
More Examples


Enforcing naming rules
       We don’t want classes with attributes that are not lowercase to be ever
       created !!!!
 class InvalidAttribName(TypeError): pass
 class MetaEnsureAttribNames(type):
     def __new__(mcl, name, bases, attrs):
         invalids = [attr for attr in attrs
                          if not attr.islower()]
         if invalids:
             msg = quot;Invalid Attributes: quot; + quot;, quot;.join(invalids)
             raise InvalidAttribName, msg
         super_ = super(MetaEnsureAttribNames, mcl)
         return super_.__new__(mcl, name, bases, attrs)
 class EnsureAttribNames(object):
     __metaclass__ = MetaEnsureAttribNames

       (You can experiment with different rules for methods, rules for class names,
       etc.)

J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses         December 2008   16 / 21
More Examples


Checking Whether Interfaces are Implemented
       We want to extend python capabilities to respresent the idea of an interface
       and to ensure that a class that declares implementing one, actually does it
       Interfaces are represented by simple classes

 class IConnectable(object):
     def send(self, msg): pass
     def receive(self): pass

       Declaring an interface is done with a class’ attribute and is ensured by a
       metaclass
 class Channel(object):
     __metaclass__ = MetaInterfaceChecker
     __implements__ = IConnectable
     def send(self, msg): ....
     def receive(self): ....




J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses           December 2008   17 / 21
More Examples


Checking Whether Interfaces are Implemented
       We want to extend python capabilities to respresent the idea of an interface
       and to ensure that a class that declares implementing one, actually does it
       Interfaces are represented by simple classes

 class IConnectable(object):
     def send(self, msg): pass
     def receive(self): pass

       Declaring an interface is done with a class’ attribute and is ensured by a
       metaclass
 class Channel(object):
     __metaclass__ = MetaInterfaceChecker
     __implements__ = IConnectable
     def send(self, msg): ....
     def receive(self): ....




J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses           December 2008   17 / 21
More Examples


Checking Whether Interfaces are Implemented
       We want to extend python capabilities to respresent the idea of an interface
       and to ensure that a class that declares implementing one, actually does it
       Interfaces are represented by simple classes

 class IConnectable(object):
     def send(self, msg): pass
     def receive(self): pass

       Declaring an interface is done with a class’ attribute and is ensured by a
       metaclass
 class Channel(object):
     __metaclass__ = MetaInterfaceChecker
     __implements__ = IConnectable
     def send(self, msg): ....
     def receive(self): ....




J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses           December 2008   17 / 21
More Examples


Checking Whether Interfaces are Implemented
       We want to extend python capabilities to respresent the idea of an interface
       and to ensure that a class that declares implementing one, actually does it
       Interfaces are represented by simple classes

 class IConnectable(object):
     def send(self, msg): pass
     def receive(self): pass

       Declaring an interface is done with a class’ attribute and is ensured by a
       metaclass
 class Channel(object):
     __metaclass__ = MetaInterfaceChecker
     __implements__ = IConnectable
     def send(self, msg): ....
     def receive(self): ....




J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses           December 2008   17 / 21
More Examples


Checking Whether Interfaces are Implemented
       We want to extend python capabilities to respresent the idea of an interface
       and to ensure that a class that declares implementing one, actually does it
       Interfaces are represented by simple classes

 class IConnectable(object):
     def send(self, msg): pass
     def receive(self): pass

       Declaring an interface is done with a class’ attribute and is ensured by a
       metaclass
 class Channel(object):
     __metaclass__ = MetaInterfaceChecker
     __implements__ = IConnectable
     def send(self, msg): ....
     def receive(self): ....




J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses           December 2008   17 / 21
More Examples


Checking Whether Interfaces are Implemented
       The following metaclass checks if all the methods in all declared interfaces are
       defined in the class
       (The implementation is na¨ so you can enhance it. hint: use module
                                 ıve,
       inspect)

 import set
 class InterfaceOmission(TypeError): pass
 class MetaInterfaceChecker(type):
     def __init__(cls, classname, bases, classdict):
         super(MetaInterfaceChecker, cls).__init__(classname,
                                                   bases,
                                                   classdict)
         cls_defines = set(dir(cls))
         for interface in cls.__implements__:
             itf_requires = set(dir(interface))
             if not itf_requires.issubset(cls_defines):
                 raise (InterfaceOmission,
                        list(itf_requires - cls_defines))

J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses            December 2008   18 / 21
More Examples


Checking Whether Interfaces are Implemented
       The following metaclass checks if all the methods in all declared interfaces are
       defined in the class
       (The implementation is na¨ so you can enhance it. hint: use module
                                 ıve,
       inspect)

 import set
 class InterfaceOmission(TypeError): pass
 class MetaInterfaceChecker(type):
     def __init__(cls, classname, bases, classdict):
         super(MetaInterfaceChecker, cls).__init__(classname,
                                                   bases,
                                                   classdict)
         cls_defines = set(dir(cls))
         for interface in cls.__implements__:
             itf_requires = set(dir(interface))
             if not itf_requires.issubset(cls_defines):
                 raise (InterfaceOmission,
                        list(itf_requires - cls_defines))

J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses            December 2008   18 / 21
More Examples


Checking Whether Interfaces are Implemented
       The following metaclass checks if all the methods in all declared interfaces are
       defined in the class
       (The implementation is na¨ so you can enhance it. hint: use module
                                 ıve,
       inspect)

 import set
 class InterfaceOmission(TypeError): pass
 class MetaInterfaceChecker(type):
     def __init__(cls, classname, bases, classdict):
         super(MetaInterfaceChecker, cls).__init__(classname,
                                                   bases,
                                                   classdict)
         cls_defines = set(dir(cls))
         for interface in cls.__implements__:
             itf_requires = set(dir(interface))
             if not itf_requires.issubset(cls_defines):
                 raise (InterfaceOmission,
                        list(itf_requires - cls_defines))

J.M.Gimeno (jmgimeno@diei.udl.cat)            Metaclasses            December 2008   18 / 21
Concluding Remarks


Conclusions



        Metaclasses must not be abused
               they put you dangerously near to the dark side
               if there’s a simple way to perform the same, don’t use them
               but sometimes they simplify things
               or lead to more efficient solutions
        But understanding them
               shows you the whole picture of python’s OO
               gives you new ways to think about solutions
        And they are fun !!!




J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses     December 2008   19 / 21
Concluding Remarks


Conclusions



        Metaclasses must not be abused
               they put you dangerously near to the dark side
               if there’s a simple way to perform the same, don’t use them
               but sometimes they simplify things
               or lead to more efficient solutions
        But understanding them
               shows you the whole picture of python’s OO
               gives you new ways to think about solutions
        And they are fun !!!




J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses     December 2008   19 / 21
Concluding Remarks


Conclusions



        Metaclasses must not be abused
               they put you dangerously near to the dark side
               if there’s a simple way to perform the same, don’t use them
               but sometimes they simplify things
               or lead to more efficient solutions
        But understanding them
               shows you the whole picture of python’s OO
               gives you new ways to think about solutions
        And they are fun !!!




J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses     December 2008   19 / 21
Concluding Remarks


Conclusions



        Metaclasses must not be abused
               they put you dangerously near to the dark side
               if there’s a simple way to perform the same, don’t use them
               but sometimes they simplify things
               or lead to more efficient solutions
        But understanding them
               shows you the whole picture of python’s OO
               gives you new ways to think about solutions
        And they are fun !!!




J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses     December 2008   19 / 21
Concluding Remarks


Conclusions



        Metaclasses must not be abused
               they put you dangerously near to the dark side
               if there’s a simple way to perform the same, don’t use them
               but sometimes they simplify things
               or lead to more efficient solutions
        But understanding them
               shows you the whole picture of python’s OO
               gives you new ways to think about solutions
        And they are fun !!!




J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses     December 2008   19 / 21
Concluding Remarks


Conclusions



        Metaclasses must not be abused
               they put you dangerously near to the dark side
               if there’s a simple way to perform the same, don’t use them
               but sometimes they simplify things
               or lead to more efficient solutions
        But understanding them
               shows you the whole picture of python’s OO
               gives you new ways to think about solutions
        And they are fun !!!




J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses     December 2008   19 / 21
Concluding Remarks


Conclusions



        Metaclasses must not be abused
               they put you dangerously near to the dark side
               if there’s a simple way to perform the same, don’t use them
               but sometimes they simplify things
               or lead to more efficient solutions
        But understanding them
               shows you the whole picture of python’s OO
               gives you new ways to think about solutions
        And they are fun !!!




J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses     December 2008   19 / 21
Concluding Remarks


Conclusions



        Metaclasses must not be abused
               they put you dangerously near to the dark side
               if there’s a simple way to perform the same, don’t use them
               but sometimes they simplify things
               or lead to more efficient solutions
        But understanding them
               shows you the whole picture of python’s OO
               gives you new ways to think about solutions
        And they are fun !!!




J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses     December 2008   19 / 21
Concluding Remarks


Conclusions



        Metaclasses must not be abused
               they put you dangerously near to the dark side
               if there’s a simple way to perform the same, don’t use them
               but sometimes they simplify things
               or lead to more efficient solutions
        But understanding them
               shows you the whole picture of python’s OO
               gives you new ways to think about solutions
        And they are fun !!!




J.M.Gimeno (jmgimeno@diei.udl.cat)                 Metaclasses     December 2008   19 / 21
Bibliography


Bibliography
        Shalahb Chaturvedi, Python Types and Objects
        Mike Fletcher, Metaclasses, Who, Why, When, Python Conference
        (Pycon) 2004.
        Ira R. Forman and Scott Danforth, Putting Metaclasses to Work.
        Addison-Wesley, 1999.
        Alex Martelli, Python in a Nutshell (2nd Edition), O’Reilly Media Inc,
        2006.
        Alex Martelli, Python Metaclasses
        Alex Martelli, Anna Martelli, Python Cookbook (2nd Edition),
        O’Reilly Media Inc, 2005.
        The recipes are based on those in ActiveState Python Cookbook.
        David Mertz, A Primer on Python Metaclass Programming
        Guido Van Rossum, Unifying types and classes in Python 2.2

J.M.Gimeno (jmgimeno@diei.udl.cat)           Metaclasses     December 2008   20 / 21
License


License

 Aquesta obra est` subjecta a una llic`ncia Reconeixement-Compartir amb
                   a                  e
 la mateixa llic`ncia 2.5 Espanya de Creative Commons.
                e
 Per veure’n una c`pia, visiteu
                    o

                 http://creativecommons.org/licenses/by-sa/2.5/es/

 o envieu una carta a
                                Creative Commons
                                559 Nathan Abbott Way
                                Stanford
                                California 94305
                                USA




J.M.Gimeno (jmgimeno@diei.udl.cat)         Metaclasses       December 2008   21 / 21

Weitere ähnliche Inhalte

Ähnlich wie Metaclass Programming in Python

L ab # 07
L ab # 07L ab # 07
L ab # 07
Mr SMAK
 
Regex,functions, inheritance,class, attribute,overloding
Regex,functions, inheritance,class, attribute,overlodingRegex,functions, inheritance,class, attribute,overloding
Regex,functions, inheritance,class, attribute,overloding
sangumanikesh
 
Relationships and their representation in a class diagram.pptx
Relationships and their representation in a class diagram.pptxRelationships and their representation in a class diagram.pptx
Relationships and their representation in a class diagram.pptx
nesarahmad37
 
Object in python tells about object oriented programming in python
Object in python tells about object oriented programming in pythonObject in python tells about object oriented programming in python
Object in python tells about object oriented programming in python
ReshmiShaw2
 

Ähnlich wie Metaclass Programming in Python (20)

Metaclasses – Python’s Object-Oriented Paradigm and Its Metaprogramming
Metaclasses – Python’s Object-Oriented Paradigm and Its MetaprogrammingMetaclasses – Python’s Object-Oriented Paradigm and Its Metaprogramming
Metaclasses – Python’s Object-Oriented Paradigm and Its Metaprogramming
 
Object oriented programming tutorial
Object oriented programming tutorialObject oriented programming tutorial
Object oriented programming tutorial
 
L ab # 07
L ab # 07L ab # 07
L ab # 07
 
IPP-M5-C1-Classes _ Objects python -S2.pptx
IPP-M5-C1-Classes _ Objects python -S2.pptxIPP-M5-C1-Classes _ Objects python -S2.pptx
IPP-M5-C1-Classes _ Objects python -S2.pptx
 
Class and object 1
Class and object 1Class and object 1
Class and object 1
 
Python data modelling
Python data modellingPython data modelling
Python data modelling
 
Python - object oriented
Python - object orientedPython - object oriented
Python - object oriented
 
OOP.pptx
OOP.pptxOOP.pptx
OOP.pptx
 
Object Oriented Programming.pptx
Object Oriented Programming.pptxObject Oriented Programming.pptx
Object Oriented Programming.pptx
 
CLASS & OBJECT IN JAVA
CLASS & OBJECT  IN JAVACLASS & OBJECT  IN JAVA
CLASS & OBJECT IN JAVA
 
OOSD1-unit1_1_16_09.pptx
OOSD1-unit1_1_16_09.pptxOOSD1-unit1_1_16_09.pptx
OOSD1-unit1_1_16_09.pptx
 
6- What are the differences between objects and abstract data typesSol.docx
6- What are the differences between objects and abstract data typesSol.docx6- What are the differences between objects and abstract data typesSol.docx
6- What are the differences between objects and abstract data typesSol.docx
 
Python-Classes.pptx
Python-Classes.pptxPython-Classes.pptx
Python-Classes.pptx
 
Regex,functions, inheritance,class, attribute,overloding
Regex,functions, inheritance,class, attribute,overlodingRegex,functions, inheritance,class, attribute,overloding
Regex,functions, inheritance,class, attribute,overloding
 
Object Oriented Programming_Lecture 2
Object Oriented Programming_Lecture 2Object Oriented Programming_Lecture 2
Object Oriented Programming_Lecture 2
 
python.pptx
python.pptxpython.pptx
python.pptx
 
Chapter 7 java
Chapter 7 javaChapter 7 java
Chapter 7 java
 
Relationships and their representation in a class diagram.pptx
Relationships and their representation in a class diagram.pptxRelationships and their representation in a class diagram.pptx
Relationships and their representation in a class diagram.pptx
 
O6u CS-315A OOP Lecture (1).pdf
O6u CS-315A OOP Lecture (1).pdfO6u CS-315A OOP Lecture (1).pdf
O6u CS-315A OOP Lecture (1).pdf
 
Object in python tells about object oriented programming in python
Object in python tells about object oriented programming in pythonObject in python tells about object oriented programming in python
Object in python tells about object oriented programming in python
 

Mehr von Juan-Manuel Gimeno (8)

Visualización de datos enlazados
Visualización de datos enlazadosVisualización de datos enlazados
Visualización de datos enlazados
 
Functional programming in clojure
Functional programming in clojureFunctional programming in clojure
Functional programming in clojure
 
Sistemas de recomendación
Sistemas de recomendaciónSistemas de recomendación
Sistemas de recomendación
 
Proves de Software (en Java amb JUnit)
Proves de Software (en Java amb JUnit)Proves de Software (en Java amb JUnit)
Proves de Software (en Java amb JUnit)
 
Conceptes bàsics de la Web 2.0
Conceptes bàsics de la Web 2.0Conceptes bàsics de la Web 2.0
Conceptes bàsics de la Web 2.0
 
Unicode (and Python)
Unicode (and Python)Unicode (and Python)
Unicode (and Python)
 
Object-oriented Programming in Python
Object-oriented Programming in PythonObject-oriented Programming in Python
Object-oriented Programming in Python
 
Python: the Project, the Language and the Style
Python: the Project, the Language and the StylePython: the Project, the Language and the Style
Python: the Project, the Language and the Style
 

Kürzlich hochgeladen

1029 - Danh muc Sach Giao Khoa 10 . pdf
1029 -  Danh muc Sach Giao Khoa 10 . pdf1029 -  Danh muc Sach Giao Khoa 10 . pdf
1029 - Danh muc Sach Giao Khoa 10 . pdf
QucHHunhnh
 
1029-Danh muc Sach Giao Khoa khoi 6.pdf
1029-Danh muc Sach Giao Khoa khoi  6.pdf1029-Danh muc Sach Giao Khoa khoi  6.pdf
1029-Danh muc Sach Giao Khoa khoi 6.pdf
QucHHunhnh
 
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
ZurliaSoop
 
Vishram Singh - Textbook of Anatomy Upper Limb and Thorax.. Volume 1 (1).pdf
Vishram Singh - Textbook of Anatomy  Upper Limb and Thorax.. Volume 1 (1).pdfVishram Singh - Textbook of Anatomy  Upper Limb and Thorax.. Volume 1 (1).pdf
Vishram Singh - Textbook of Anatomy Upper Limb and Thorax.. Volume 1 (1).pdf
ssuserdda66b
 

Kürzlich hochgeladen (20)

Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
 
1029 - Danh muc Sach Giao Khoa 10 . pdf
1029 -  Danh muc Sach Giao Khoa 10 . pdf1029 -  Danh muc Sach Giao Khoa 10 . pdf
1029 - Danh muc Sach Giao Khoa 10 . pdf
 
Google Gemini An AI Revolution in Education.pptx
Google Gemini An AI Revolution in Education.pptxGoogle Gemini An AI Revolution in Education.pptx
Google Gemini An AI Revolution in Education.pptx
 
Unit-IV- Pharma. Marketing Channels.pptx
Unit-IV- Pharma. Marketing Channels.pptxUnit-IV- Pharma. Marketing Channels.pptx
Unit-IV- Pharma. Marketing Channels.pptx
 
Unit-IV; Professional Sales Representative (PSR).pptx
Unit-IV; Professional Sales Representative (PSR).pptxUnit-IV; Professional Sales Representative (PSR).pptx
Unit-IV; Professional Sales Representative (PSR).pptx
 
Introduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The BasicsIntroduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The Basics
 
Holdier Curriculum Vitae (April 2024).pdf
Holdier Curriculum Vitae (April 2024).pdfHoldier Curriculum Vitae (April 2024).pdf
Holdier Curriculum Vitae (April 2024).pdf
 
UGC NET Paper 1 Mathematical Reasoning & Aptitude.pdf
UGC NET Paper 1 Mathematical Reasoning & Aptitude.pdfUGC NET Paper 1 Mathematical Reasoning & Aptitude.pdf
UGC NET Paper 1 Mathematical Reasoning & Aptitude.pdf
 
How to Give a Domain for a Field in Odoo 17
How to Give a Domain for a Field in Odoo 17How to Give a Domain for a Field in Odoo 17
How to Give a Domain for a Field in Odoo 17
 
1029-Danh muc Sach Giao Khoa khoi 6.pdf
1029-Danh muc Sach Giao Khoa khoi  6.pdf1029-Danh muc Sach Giao Khoa khoi  6.pdf
1029-Danh muc Sach Giao Khoa khoi 6.pdf
 
Understanding Accommodations and Modifications
Understanding  Accommodations and ModificationsUnderstanding  Accommodations and Modifications
Understanding Accommodations and Modifications
 
Python Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docxPython Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docx
 
Basic Civil Engineering first year Notes- Chapter 4 Building.pptx
Basic Civil Engineering first year Notes- Chapter 4 Building.pptxBasic Civil Engineering first year Notes- Chapter 4 Building.pptx
Basic Civil Engineering first year Notes- Chapter 4 Building.pptx
 
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
 
Mixin Classes in Odoo 17 How to Extend Models Using Mixin Classes
Mixin Classes in Odoo 17  How to Extend Models Using Mixin ClassesMixin Classes in Odoo 17  How to Extend Models Using Mixin Classes
Mixin Classes in Odoo 17 How to Extend Models Using Mixin Classes
 
Unit-V; Pricing (Pharma Marketing Management).pptx
Unit-V; Pricing (Pharma Marketing Management).pptxUnit-V; Pricing (Pharma Marketing Management).pptx
Unit-V; Pricing (Pharma Marketing Management).pptx
 
Fostering Friendships - Enhancing Social Bonds in the Classroom
Fostering Friendships - Enhancing Social Bonds  in the ClassroomFostering Friendships - Enhancing Social Bonds  in the Classroom
Fostering Friendships - Enhancing Social Bonds in the Classroom
 
How to Manage Global Discount in Odoo 17 POS
How to Manage Global Discount in Odoo 17 POSHow to Manage Global Discount in Odoo 17 POS
How to Manage Global Discount in Odoo 17 POS
 
Vishram Singh - Textbook of Anatomy Upper Limb and Thorax.. Volume 1 (1).pdf
Vishram Singh - Textbook of Anatomy  Upper Limb and Thorax.. Volume 1 (1).pdfVishram Singh - Textbook of Anatomy  Upper Limb and Thorax.. Volume 1 (1).pdf
Vishram Singh - Textbook of Anatomy Upper Limb and Thorax.. Volume 1 (1).pdf
 
SOC 101 Demonstration of Learning Presentation
SOC 101 Demonstration of Learning PresentationSOC 101 Demonstration of Learning Presentation
SOC 101 Demonstration of Learning Presentation
 

Metaclass Programming in Python

  • 1. Metaclass Programming in Python Advanced OO concepts Juan Manuel Gimeno Illa jmgimeno@diei.udl.cat December 2008 J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 1 / 21
  • 2. This is dangerous, so don’t do it at home :-) [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 (c.l.p post 2002-12-22) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 2 / 21
  • 3. Outline 1 Basic Concepts 2 How classes are created Inside class statement Metaclass Programming Metaclass Conflicts 3 More Examples 4 Concluding Remarks J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 3 / 21
  • 4. Basic Concepts Objects and Classes Classes are templates used to create objects that share structure (attributes) and behaviour (methods) but have different state (attributes’ values) For object obj, type(obj) is the class or type of obj For object obj, type(type(obj)) is the metaclass or metatype of obj (Sometimes type(type(obj)) is referred as the metaclass of type(obj) but this is incorrect) The same way that classes shape objects, metaclasses shape classes. For instance, in Python, the difference between new and old classes resides in the metaclass used to create the classes (Note that the difference in metaclass can affect the objects of the classes. For instance, instances of new-style classes behave differently than those of old-style ones) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 4 / 21
  • 5. Basic Concepts Objects and Classes Classes are templates used to create objects that share structure (attributes) and behaviour (methods) but have different state (attributes’ values) For object obj, type(obj) is the class or type of obj For object obj, type(type(obj)) is the metaclass or metatype of obj (Sometimes type(type(obj)) is referred as the metaclass of type(obj) but this is incorrect) The same way that classes shape objects, metaclasses shape classes. For instance, in Python, the difference between new and old classes resides in the metaclass used to create the classes (Note that the difference in metaclass can affect the objects of the classes. For instance, instances of new-style classes behave differently than those of old-style ones) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 4 / 21
  • 6. Basic Concepts Objects and Classes Classes are templates used to create objects that share structure (attributes) and behaviour (methods) but have different state (attributes’ values) For object obj, type(obj) is the class or type of obj For object obj, type(type(obj)) is the metaclass or metatype of obj (Sometimes type(type(obj)) is referred as the metaclass of type(obj) but this is incorrect) The same way that classes shape objects, metaclasses shape classes. For instance, in Python, the difference between new and old classes resides in the metaclass used to create the classes (Note that the difference in metaclass can affect the objects of the classes. For instance, instances of new-style classes behave differently than those of old-style ones) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 4 / 21
  • 7. Basic Concepts Objects and Classes Classes are templates used to create objects that share structure (attributes) and behaviour (methods) but have different state (attributes’ values) For object obj, type(obj) is the class or type of obj For object obj, type(type(obj)) is the metaclass or metatype of obj (Sometimes type(type(obj)) is referred as the metaclass of type(obj) but this is incorrect) The same way that classes shape objects, metaclasses shape classes. For instance, in Python, the difference between new and old classes resides in the metaclass used to create the classes (Note that the difference in metaclass can affect the objects of the classes. For instance, instances of new-style classes behave differently than those of old-style ones) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 4 / 21
  • 8. Basic Concepts Objects and Classes Classes are templates used to create objects that share structure (attributes) and behaviour (methods) but have different state (attributes’ values) For object obj, type(obj) is the class or type of obj For object obj, type(type(obj)) is the metaclass or metatype of obj (Sometimes type(type(obj)) is referred as the metaclass of type(obj) but this is incorrect) The same way that classes shape objects, metaclasses shape classes. For instance, in Python, the difference between new and old classes resides in the metaclass used to create the classes (Note that the difference in metaclass can affect the objects of the classes. For instance, instances of new-style classes behave differently than those of old-style ones) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 4 / 21
  • 9. Basic Concepts Objects and Classes Classes are templates used to create objects that share structure (attributes) and behaviour (methods) but have different state (attributes’ values) For object obj, type(obj) is the class or type of obj For object obj, type(type(obj)) is the metaclass or metatype of obj (Sometimes type(type(obj)) is referred as the metaclass of type(obj) but this is incorrect) The same way that classes shape objects, metaclasses shape classes. For instance, in Python, the difference between new and old classes resides in the metaclass used to create the classes (Note that the difference in metaclass can affect the objects of the classes. For instance, instances of new-style classes behave differently than those of old-style ones) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 4 / 21
  • 10. Basic Concepts Objects and Classes Classes are templates used to create objects that share structure (attributes) and behaviour (methods) but have different state (attributes’ values) For object obj, type(obj) is the class or type of obj For object obj, type(type(obj)) is the metaclass or metatype of obj (Sometimes type(type(obj)) is referred as the metaclass of type(obj) but this is incorrect) The same way that classes shape objects, metaclasses shape classes. For instance, in Python, the difference between new and old classes resides in the metaclass used to create the classes (Note that the difference in metaclass can affect the objects of the classes. For instance, instances of new-style classes behave differently than those of old-style ones) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 4 / 21
  • 11. Basic Concepts Objects and Classes Classes are templates used to create objects that share structure (attributes) and behaviour (methods) but have different state (attributes’ values) For object obj, type(obj) is the class or type of obj For object obj, type(type(obj)) is the metaclass or metatype of obj (Sometimes type(type(obj)) is referred as the metaclass of type(obj) but this is incorrect) The same way that classes shape objects, metaclasses shape classes. For instance, in Python, the difference between new and old classes resides in the metaclass used to create the classes (Note that the difference in metaclass can affect the objects of the classes. For instance, instances of new-style classes behave differently than those of old-style ones) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 4 / 21
  • 12. Basic Concepts Objects and Classes Classes are templates used to create objects that share structure (attributes) and behaviour (methods) but have different state (attributes’ values) For object obj, type(obj) is the class or type of obj For object obj, type(type(obj)) is the metaclass or metatype of obj (Sometimes type(type(obj)) is referred as the metaclass of type(obj) but this is incorrect) The same way that classes shape objects, metaclasses shape classes. For instance, in Python, the difference between new and old classes resides in the metaclass used to create the classes (Note that the difference in metaclass can affect the objects of the classes. For instance, instances of new-style classes behave differently than those of old-style ones) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 4 / 21
  • 13. Basic Concepts New and Old Classes >>> class New(object): pass ... >>> class Old: pass ... Differences in new and >>> n = New() old style objects (for >>> o = Old() instance, the mro of >>> type(n) attributes) . . . <class ’ main .New’> >>> type(o) . . . are due to the <type ’instance’> different metaclasses >>> type(New) they have <type ’type’> >>> type(Old) <type ’classobj’> J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 5 / 21
  • 14. Basic Concepts New and Old Classes >>> class New(object): pass ... >>> class Old: pass ... Differences in new and >>> n = New() old style objects (for >>> o = Old() instance, the mro of >>> type(n) attributes) . . . <class ’ main .New’> >>> type(o) . . . are due to the <type ’instance’> different metaclasses >>> type(New) they have <type ’type’> >>> type(Old) <type ’classobj’> J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 5 / 21
  • 15. Basic Concepts New and Old Classes >>> class New(object): pass ... >>> class Old: pass ... Differences in new and >>> n = New() old style objects (for >>> o = Old() instance, the mro of >>> type(n) attributes) . . . <class ’ main .New’> >>> type(o) . . . are due to the <type ’instance’> different metaclasses >>> type(New) they have <type ’type’> >>> type(Old) <type ’classobj’> J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 5 / 21
  • 16. Basic Concepts New and Old Classes >>> class New(object): pass ... >>> class Old: pass ... Differences in new and >>> n = New() old style objects (for >>> o = Old() instance, the mro of >>> type(n) attributes) . . . <class ’ main .New’> >>> type(o) . . . are due to the <type ’instance’> different metaclasses >>> type(New) they have <type ’type’> >>> type(Old) <type ’classobj’> J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 5 / 21
  • 17. Basic Concepts New and Old Classes >>> class New(object): pass ... >>> class Old: pass ... Differences in new and >>> n = New() old style objects (for >>> o = Old() instance, the mro of >>> type(n) attributes) . . . <class ’ main .New’> >>> type(o) . . . are due to the <type ’instance’> different metaclasses >>> type(New) they have <type ’type’> >>> type(Old) <type ’classobj’> J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 5 / 21
  • 18. How classes are created Inside class statement The built-in type type(name, bases, attribs)(a.k.a types.TypeType) creates a new-style class object name is a string containing the name of the class (C. name ) bases is a tuple containing the base classes for the new class (C. bases ) attribs is a dictionary pairing the attribute’s names with their corresponding values So the usual class statement (when dealing with new-style classes) class Class(base1, base2, ...): statements calls type with parameters ‘‘Class’’, (base1, base2, ...) and a dictionary containing the bindings created by the execution of the statements. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 6 / 21
  • 19. How classes are created Inside class statement The built-in type type(name, bases, attribs)(a.k.a types.TypeType) creates a new-style class object name is a string containing the name of the class (C. name ) bases is a tuple containing the base classes for the new class (C. bases ) attribs is a dictionary pairing the attribute’s names with their corresponding values So the usual class statement (when dealing with new-style classes) class Class(base1, base2, ...): statements calls type with parameters ‘‘Class’’, (base1, base2, ...) and a dictionary containing the bindings created by the execution of the statements. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 6 / 21
  • 20. How classes are created Inside class statement The built-in type type(name, bases, attribs)(a.k.a types.TypeType) creates a new-style class object name is a string containing the name of the class (C. name ) bases is a tuple containing the base classes for the new class (C. bases ) attribs is a dictionary pairing the attribute’s names with their corresponding values So the usual class statement (when dealing with new-style classes) class Class(base1, base2, ...): statements calls type with parameters ‘‘Class’’, (base1, base2, ...) and a dictionary containing the bindings created by the execution of the statements. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 6 / 21
  • 21. How classes are created Inside class statement The built-in type type(name, bases, attribs)(a.k.a types.TypeType) creates a new-style class object name is a string containing the name of the class (C. name ) bases is a tuple containing the base classes for the new class (C. bases ) attribs is a dictionary pairing the attribute’s names with their corresponding values So the usual class statement (when dealing with new-style classes) class Class(base1, base2, ...): statements calls type with parameters ‘‘Class’’, (base1, base2, ...) and a dictionary containing the bindings created by the execution of the statements. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 6 / 21
  • 22. How classes are created Inside class statement The built-in type type(name, bases, attribs)(a.k.a types.TypeType) creates a new-style class object name is a string containing the name of the class (C. name ) bases is a tuple containing the base classes for the new class (C. bases ) attribs is a dictionary pairing the attribute’s names with their corresponding values So the usual class statement (when dealing with new-style classes) class Class(base1, base2, ...): statements calls type with parameters ‘‘Class’’, (base1, base2, ...) and a dictionary containing the bindings created by the execution of the statements. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 6 / 21
  • 23. How classes are created Inside class statement Inside the class statement When one defines a new-style class: >>> class Class1(object): ... attrib = 1 ... def __init__(self, n): ... self.n = n One actually executes: >>> class_name = quot;Class1quot; >>> class_bases = (object,) >>> class_dict = {} >>> class_body = quot;quot;quot; attrib = 1 def __init__(self, n): self.n = n quot;quot;quot; >>> exec class_body in globals(), class_dict >>> locals()[class_name] = type(class_name, class_bases, class_dict) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 7 / 21
  • 24. How classes are created Inside class statement Inside the class statement When one defines a new-style class: >>> class Class1(object): ... attrib = 1 ... def __init__(self, n): ... self.n = n One actually executes: >>> class_name = quot;Class1quot; >>> class_bases = (object,) >>> class_dict = {} >>> class_body = quot;quot;quot; attrib = 1 def __init__(self, n): self.n = n quot;quot;quot; >>> exec class_body in globals(), class_dict >>> locals()[class_name] = type(class_name, class_bases, class_dict) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 7 / 21
  • 25. How classes are created Inside class statement Inside the class statement When one defines a new-style class: >>> class Class1(object): ... attrib = 1 ... def __init__(self, n): ... self.n = n One actually executes: >>> class_name = quot;Class1quot; >>> class_bases = (object,) >>> class_dict = {} >>> class_body = quot;quot;quot; attrib = 1 def __init__(self, n): self.n = n quot;quot;quot; >>> exec class_body in globals(), class_dict >>> locals()[class_name] = type(class_name, class_bases, class_dict) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 7 / 21
  • 26. How classes are created Inside class statement Inside the class statement When one defines a new-style class: >>> class Class1(object): ... attrib = 1 ... def __init__(self, n): ... self.n = n One actually executes: >>> class_name = quot;Class1quot; >>> class_bases = (object,) >>> class_dict = {} >>> class_body = quot;quot;quot; attrib = 1 def __init__(self, n): self.n = n quot;quot;quot; >>> exec class_body in globals(), class_dict >>> locals()[class_name] = type(class_name, class_bases, class_dict) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 7 / 21
  • 27. How classes are created Inside class statement The full truth of the class statement To execute a class statement: 1 Python first collects the class name in a string n, the base classes into a tuple t and executes the body in dictionary d 2 Then determines the metaclass to use for the new class object C 1 When metaclass is a key in d, then M = d[’ metaclass ’] 2 When t is nonempty, then M is the leafmost1 metaclass among all the metaclasses of C’s bases that are not old-style classes 3 If the current module has a global variable metaclass , then M is the value of this variable 4 Failing all of these, M defaults to types.ClassType, that is, an old-style class is created 3 Finally, C = M(n, t, d) 1 If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing this metatype conflict. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 8 / 21
  • 28. How classes are created Inside class statement The full truth of the class statement To execute a class statement: 1 Python first collects the class name in a string n, the base classes into a tuple t and executes the body in dictionary d 2 Then determines the metaclass to use for the new class object C 1 When metaclass is a key in d, then M = d[’ metaclass ’] 2 When t is nonempty, then M is the leafmost1 metaclass among all the metaclasses of C’s bases that are not old-style classes 3 If the current module has a global variable metaclass , then M is the value of this variable 4 Failing all of these, M defaults to types.ClassType, that is, an old-style class is created 3 Finally, C = M(n, t, d) 1 If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing this metatype conflict. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 8 / 21
  • 29. How classes are created Inside class statement The full truth of the class statement To execute a class statement: 1 Python first collects the class name in a string n, the base classes into a tuple t and executes the body in dictionary d 2 Then determines the metaclass to use for the new class object C 1 When metaclass is a key in d, then M = d[’ metaclass ’] 2 When t is nonempty, then M is the leafmost1 metaclass among all the metaclasses of C’s bases that are not old-style classes 3 If the current module has a global variable metaclass , then M is the value of this variable 4 Failing all of these, M defaults to types.ClassType, that is, an old-style class is created 3 Finally, C = M(n, t, d) 1 If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing this metatype conflict. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 8 / 21
  • 30. How classes are created Inside class statement The full truth of the class statement To execute a class statement: 1 Python first collects the class name in a string n, the base classes into a tuple t and executes the body in dictionary d 2 Then determines the metaclass to use for the new class object C 1 When metaclass is a key in d, then M = d[’ metaclass ’] 2 When t is nonempty, then M is the leafmost1 metaclass among all the metaclasses of C’s bases that are not old-style classes 3 If the current module has a global variable metaclass , then M is the value of this variable 4 Failing all of these, M defaults to types.ClassType, that is, an old-style class is created 3 Finally, C = M(n, t, d) 1 If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing this metatype conflict. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 8 / 21
  • 31. How classes are created Inside class statement The full truth of the class statement To execute a class statement: 1 Python first collects the class name in a string n, the base classes into a tuple t and executes the body in dictionary d 2 Then determines the metaclass to use for the new class object C 1 When metaclass is a key in d, then M = d[’ metaclass ’] 2 When t is nonempty, then M is the leafmost1 metaclass among all the metaclasses of C’s bases that are not old-style classes 3 If the current module has a global variable metaclass , then M is the value of this variable 4 Failing all of these, M defaults to types.ClassType, that is, an old-style class is created 3 Finally, C = M(n, t, d) 1 If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing this metatype conflict. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 8 / 21
  • 32. How classes are created Inside class statement The full truth of the class statement To execute a class statement: 1 Python first collects the class name in a string n, the base classes into a tuple t and executes the body in dictionary d 2 Then determines the metaclass to use for the new class object C 1 When metaclass is a key in d, then M = d[’ metaclass ’] 2 When t is nonempty, then M is the leafmost1 metaclass among all the metaclasses of C’s bases that are not old-style classes 3 If the current module has a global variable metaclass , then M is the value of this variable 4 Failing all of these, M defaults to types.ClassType, that is, an old-style class is created 3 Finally, C = M(n, t, d) 1 If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing this metatype conflict. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 8 / 21
  • 33. How classes are created Inside class statement The full truth of the class statement To execute a class statement: 1 Python first collects the class name in a string n, the base classes into a tuple t and executes the body in dictionary d 2 Then determines the metaclass to use for the new class object C 1 When metaclass is a key in d, then M = d[’ metaclass ’] 2 When t is nonempty, then M is the leafmost1 metaclass among all the metaclasses of C’s bases that are not old-style classes 3 If the current module has a global variable metaclass , then M is the value of this variable 4 Failing all of these, M defaults to types.ClassType, that is, an old-style class is created 3 Finally, C = M(n, t, d) 1 If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing this metatype conflict. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 8 / 21
  • 34. How classes are created Inside class statement The full truth of the class statement To execute a class statement: 1 Python first collects the class name in a string n, the base classes into a tuple t and executes the body in dictionary d 2 Then determines the metaclass to use for the new class object C 1 When metaclass is a key in d, then M = d[’ metaclass ’] 2 When t is nonempty, then M is the leafmost1 metaclass among all the metaclasses of C’s bases that are not old-style classes 3 If the current module has a global variable metaclass , then M is the value of this variable 4 Failing all of these, M defaults to types.ClassType, that is, an old-style class is created 3 Finally, C = M(n, t, d) 1 If the metaclasses of C’s bases’ do not form an inheritance lattice including its lower bound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosing this metatype conflict. J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 8 / 21
  • 35. How classes are created Metaclass Programming A very simple metaclass Redefining method repr in class changes the way python show its instances So to change the way python shows a class, we redefine repr in the metaclass >>> class MetaPretty(type): ... def __repr__(cls): ... return quot;I’m the class %squot; % cls.__name__ ... >>> class Ugly: pass >>> Ugly <class ’__main__.Ugly’> >>> class Pretty(object): ... __metaclass__ = MetaPretty >>> Pretty I’m the class Pretty Metaclass programming is easier than you thought !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 9 / 21
  • 36. How classes are created Metaclass Programming A very simple metaclass Redefining method repr in class changes the way python show its instances So to change the way python shows a class, we redefine repr in the metaclass >>> class MetaPretty(type): ... def __repr__(cls): ... return quot;I’m the class %squot; % cls.__name__ ... >>> class Ugly: pass >>> Ugly <class ’__main__.Ugly’> >>> class Pretty(object): ... __metaclass__ = MetaPretty >>> Pretty I’m the class Pretty Metaclass programming is easier than you thought !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 9 / 21
  • 37. How classes are created Metaclass Programming A very simple metaclass Redefining method repr in class changes the way python show its instances So to change the way python shows a class, we redefine repr in the metaclass >>> class MetaPretty(type): ... def __repr__(cls): ... return quot;I’m the class %squot; % cls.__name__ ... >>> class Ugly: pass >>> Ugly <class ’__main__.Ugly’> >>> class Pretty(object): ... __metaclass__ = MetaPretty >>> Pretty I’m the class Pretty Metaclass programming is easier than you thought !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 9 / 21
  • 38. How classes are created Metaclass Programming A very simple metaclass Redefining method repr in class changes the way python show its instances So to change the way python shows a class, we redefine repr in the metaclass >>> class MetaPretty(type): ... def __repr__(cls): ... return quot;I’m the class %squot; % cls.__name__ ... >>> class Ugly: pass >>> Ugly <class ’__main__.Ugly’> >>> class Pretty(object): ... __metaclass__ = MetaPretty >>> Pretty I’m the class Pretty Metaclass programming is easier than you thought !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 9 / 21
  • 39. How classes are created Metaclass Programming Automatic property creation I We don’t want to tell python the properties defined in a class if there are methods in the class that evidently want a property defined !!! We implement it redefining init class MetaAutoProp(type): def __init__(cls, name, bases, dict): super(MetaAutoProp, cls).__init__(name, bases, dict) props = set(name[5:] for name in dict.iterkeys() if name.startswith(quot;_get_quot;) or name.startswith(quot;_set_quot;)) for name in props: fget = getattr(cls, quot;_get_%squot; % name, None) fset = getattr(cls, quot;_set_%squot; % name, None) setattr(cls, name, property(fget, fset)) class AutoProp(object): __metaclass__ = MetaAutoProp class UseX(AutoProp): def __init__(self): self.__x = 0 def _get_x(self): return self.__x def _set_x(self, x): self.__x = x J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 10 / 21
  • 40. How classes are created Metaclass Programming Automatic property creation I We don’t want to tell python the properties defined in a class if there are methods in the class that evidently want a property defined !!! We implement it redefining init class MetaAutoProp(type): def __init__(cls, name, bases, dict): super(MetaAutoProp, cls).__init__(name, bases, dict) props = set(name[5:] for name in dict.iterkeys() if name.startswith(quot;_get_quot;) or name.startswith(quot;_set_quot;)) for name in props: fget = getattr(cls, quot;_get_%squot; % name, None) fset = getattr(cls, quot;_set_%squot; % name, None) setattr(cls, name, property(fget, fset)) class AutoProp(object): __metaclass__ = MetaAutoProp class UseX(AutoProp): def __init__(self): self.__x = 0 def _get_x(self): return self.__x def _set_x(self, x): self.__x = x J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 10 / 21
  • 41. How classes are created Metaclass Programming Automatic property creation I We don’t want to tell python the properties defined in a class if there are methods in the class that evidently want a property defined !!! We implement it redefining init class MetaAutoProp(type): def __init__(cls, name, bases, dict): super(MetaAutoProp, cls).__init__(name, bases, dict) props = set(name[5:] for name in dict.iterkeys() if name.startswith(quot;_get_quot;) or name.startswith(quot;_set_quot;)) for name in props: fget = getattr(cls, quot;_get_%squot; % name, None) fset = getattr(cls, quot;_set_%squot; % name, None) setattr(cls, name, property(fget, fset)) class AutoProp(object): __metaclass__ = MetaAutoProp class UseX(AutoProp): def __init__(self): self.__x = 0 def _get_x(self): return self.__x def _set_x(self, x): self.__x = x J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 10 / 21
  • 42. How classes are created Metaclass Programming Automatic property creation II The same as before but this time the implementation redefines new class MetaAutoProp(type): def __new__(mcl, classname, bases, dict): props = set(name[5:] for name in dict.iterkeys() if name.startswith(quot;_get_quot;) or name.startswith(quot;_set_quot;)) for name in props: fget = dict.get(quot;_get_%squot; % name) fset = dict.get(quot;_set_%squot; % name) dict[name] = property(fget, fset) super_ = super(MetaAutoProp, mcl) return super_.__new__(mcl, classname, bases, dict) class AutoProp(object): __metaclass__ = MetaAutoProp class UseX(AutoProp): def __init__(self): self.__x = 0 def _get_x(self): return self.__x def _set_x(self, x): self.__x = x Deciding which way to go is not clearly defined J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 11 / 21
  • 43. How classes are created Metaclass Programming Automatic property creation II The same as before but this time the implementation redefines new class MetaAutoProp(type): def __new__(mcl, classname, bases, dict): props = set(name[5:] for name in dict.iterkeys() if name.startswith(quot;_get_quot;) or name.startswith(quot;_set_quot;)) for name in props: fget = dict.get(quot;_get_%squot; % name) fset = dict.get(quot;_set_%squot; % name) dict[name] = property(fget, fset) super_ = super(MetaAutoProp, mcl) return super_.__new__(mcl, classname, bases, dict) class AutoProp(object): __metaclass__ = MetaAutoProp class UseX(AutoProp): def __init__(self): self.__x = 0 def _get_x(self): return self.__x def _set_x(self, x): self.__x = x Deciding which way to go is not clearly defined J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 11 / 21
  • 44. How classes are created Metaclass Programming Automatic property creation II The same as before but this time the implementation redefines new class MetaAutoProp(type): def __new__(mcl, classname, bases, dict): props = set(name[5:] for name in dict.iterkeys() if name.startswith(quot;_get_quot;) or name.startswith(quot;_set_quot;)) for name in props: fget = dict.get(quot;_get_%squot; % name) fset = dict.get(quot;_set_%squot; % name) dict[name] = property(fget, fset) super_ = super(MetaAutoProp, mcl) return super_.__new__(mcl, classname, bases, dict) class AutoProp(object): __metaclass__ = MetaAutoProp class UseX(AutoProp): def __init__(self): self.__x = 0 def _get_x(self): return self.__x def _set_x(self, x): self.__x = x Deciding which way to go is not clearly defined J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 11 / 21
  • 45. How classes are created Metaclass Programming Automatic Initialization of Instance Attributes import inspect class auto_attr(object): def __init__(self, factory, *args, **kwargs): self.creation_data = (factory, args, kwargs) def is_auto_attr(attr): return isinstance(attr, auto_attr) class MetaAutoAttr(type): def __call__(cls, *args, **kwargs): obj = super(MetaAutoAttr, cls).__call__(*args, **kwargs) for attr, value in inspect.getmembers(cls, is_auto_attr): factory, a, k = value.creation_data setattr(obj, attr, factory(*a, **k)) return obj class AutoAttr(object): __metaclass__ = MetaAutoAttr class Recorder(AutoAttr): count = 0 # is immutable so no shared among instances events = auto_attr(list) def record(self, event): self.count += 1 self.events.append((self.count, event)) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 12 / 21
  • 46. How classes are created Metaclass Conflicts But, sometimes, conflicts happen Imagine one wants a class with both behaviours. If one tries: from autoprop import AutoProp from autoattr import AutoAttr, auto_attr class Both(AutoProp, AutoAttr): __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, v): self.__x = v One gets: TypeError: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases The problem is that python needs to find a metaclass that brings both behaviours at the same time (This is the application of the Liskov Substitution Principle applied to metaclasses) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 13 / 21
  • 47. How classes are created Metaclass Conflicts But, sometimes, conflicts happen Imagine one wants a class with both behaviours. If one tries: from autoprop import AutoProp from autoattr import AutoAttr, auto_attr class Both(AutoProp, AutoAttr): __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, v): self.__x = v One gets: TypeError: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases The problem is that python needs to find a metaclass that brings both behaviours at the same time (This is the application of the Liskov Substitution Principle applied to metaclasses) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 13 / 21
  • 48. How classes are created Metaclass Conflicts But, sometimes, conflicts happen Imagine one wants a class with both behaviours. If one tries: from autoprop import AutoProp from autoattr import AutoAttr, auto_attr class Both(AutoProp, AutoAttr): __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, v): self.__x = v One gets: TypeError: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases The problem is that python needs to find a metaclass that brings both behaviours at the same time (This is the application of the Liskov Substitution Principle applied to metaclasses) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 13 / 21
  • 49. How classes are created Metaclass Conflicts But, sometimes, conflicts happen Imagine one wants a class with both behaviours. If one tries: from autoprop import AutoProp from autoattr import AutoAttr, auto_attr class Both(AutoProp, AutoAttr): __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, v): self.__x = v One gets: TypeError: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases The problem is that python needs to find a metaclass that brings both behaviours at the same time (This is the application of the Liskov Substitution Principle applied to metaclasses) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 13 / 21
  • 50. How classes are created Metaclass Conflicts But, sometimes, conflicts happen Imagine one wants a class with both behaviours. If one tries: from autoprop import AutoProp from autoattr import AutoAttr, auto_attr class Both(AutoProp, AutoAttr): __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, v): self.__x = v One gets: TypeError: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases The problem is that python needs to find a metaclass that brings both behaviours at the same time (This is the application of the Liskov Substitution Principle applied to metaclasses) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 13 / 21
  • 51. How classes are created Metaclass Conflicts But, sometimes, conflicts happen Imagine one wants a class with both behaviours. If one tries: from autoprop import AutoProp from autoattr import AutoAttr, auto_attr class Both(AutoProp, AutoAttr): __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, v): self.__x = v One gets: TypeError: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases The problem is that python needs to find a metaclass that brings both behaviours at the same time (This is the application of the Liskov Substitution Principle applied to metaclasses) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 13 / 21
  • 52. How classes are created Metaclass Conflicts Solving the metaclass conflict To ensured it, the metaclass to use must be a subclass of all those of the bases of the class (Technically it must be minimal in the inheritance subgraph of the metaclasses of the bases considered as a lattice) Some languages create an on-the-fly this minimal metaclass if needed Python needs you to solve the problem , so: from autoprop import MetaAutoProp from autoattr import MetaAutoAttr, auto_attr class MetaBoth(MetaAutoAttr, MetaAutoProp): pass class Both(object): __metaclass__ = MetaBoth __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, value): self.__x = value (A recipe exists in the Python Cookbook that solves this problem by defining a metaclass factory method which creates the appropriate metaclass when needed) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 14 / 21
  • 53. How classes are created Metaclass Conflicts Solving the metaclass conflict To ensured it, the metaclass to use must be a subclass of all those of the bases of the class (Technically it must be minimal in the inheritance subgraph of the metaclasses of the bases considered as a lattice) Some languages create an on-the-fly this minimal metaclass if needed Python needs you to solve the problem , so: from autoprop import MetaAutoProp from autoattr import MetaAutoAttr, auto_attr class MetaBoth(MetaAutoAttr, MetaAutoProp): pass class Both(object): __metaclass__ = MetaBoth __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, value): self.__x = value (A recipe exists in the Python Cookbook that solves this problem by defining a metaclass factory method which creates the appropriate metaclass when needed) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 14 / 21
  • 54. How classes are created Metaclass Conflicts Solving the metaclass conflict To ensured it, the metaclass to use must be a subclass of all those of the bases of the class (Technically it must be minimal in the inheritance subgraph of the metaclasses of the bases considered as a lattice) Some languages create an on-the-fly this minimal metaclass if needed Python needs you to solve the problem , so: from autoprop import MetaAutoProp from autoattr import MetaAutoAttr, auto_attr class MetaBoth(MetaAutoAttr, MetaAutoProp): pass class Both(object): __metaclass__ = MetaBoth __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, value): self.__x = value (A recipe exists in the Python Cookbook that solves this problem by defining a metaclass factory method which creates the appropriate metaclass when needed) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 14 / 21
  • 55. How classes are created Metaclass Conflicts Solving the metaclass conflict To ensured it, the metaclass to use must be a subclass of all those of the bases of the class (Technically it must be minimal in the inheritance subgraph of the metaclasses of the bases considered as a lattice) Some languages create an on-the-fly this minimal metaclass if needed Python needs you to solve the problem , so: from autoprop import MetaAutoProp from autoattr import MetaAutoAttr, auto_attr class MetaBoth(MetaAutoAttr, MetaAutoProp): pass class Both(object): __metaclass__ = MetaBoth __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, value): self.__x = value (A recipe exists in the Python Cookbook that solves this problem by defining a metaclass factory method which creates the appropriate metaclass when needed) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 14 / 21
  • 56. How classes are created Metaclass Conflicts Solving the metaclass conflict To ensured it, the metaclass to use must be a subclass of all those of the bases of the class (Technically it must be minimal in the inheritance subgraph of the metaclasses of the bases considered as a lattice) Some languages create an on-the-fly this minimal metaclass if needed Python needs you to solve the problem , so: from autoprop import MetaAutoProp from autoattr import MetaAutoAttr, auto_attr class MetaBoth(MetaAutoAttr, MetaAutoProp): pass class Both(object): __metaclass__ = MetaBoth __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, value): self.__x = value (A recipe exists in the Python Cookbook that solves this problem by defining a metaclass factory method which creates the appropriate metaclass when needed) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 14 / 21
  • 57. How classes are created Metaclass Conflicts Solving the metaclass conflict To ensured it, the metaclass to use must be a subclass of all those of the bases of the class (Technically it must be minimal in the inheritance subgraph of the metaclasses of the bases considered as a lattice) Some languages create an on-the-fly this minimal metaclass if needed Python needs you to solve the problem , so: from autoprop import MetaAutoProp from autoattr import MetaAutoAttr, auto_attr class MetaBoth(MetaAutoAttr, MetaAutoProp): pass class Both(object): __metaclass__ = MetaBoth __x = auto_attr(list) def _get_x(self): return self.__x def _set_x(self, value): self.__x = value (A recipe exists in the Python Cookbook that solves this problem by defining a metaclass factory method which creates the appropriate metaclass when needed) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 14 / 21
  • 58. More Examples Avoiding multiple initialization of Singletons The Singleton class that was presented before needed init to be idempotent. Changing its metaclass solves it: # Singleton classes are only init’ed once class Singleton(object): class __metaclass__(type): _initialized = set() def __call__(cls, *args, **kwargs): inits = Singleton.__metaclass__._initialized obj = cls.__new__(cls, *args, **kwargs) if isinstance(obj, cls) and cls not in inits: inits.add(cls) obj.__init__(*args, **kwargs) return obj _singletons = {} def __new__(cls, *args, **kwds): if cls not in cls._singletons: s = super(Singleton, cls) cls._singletons[cls] = super(Singleton, cls).__new__(cls, *args, **kwds) return cls._singletons[cls] J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 15 / 21
  • 59. More Examples Avoiding multiple initialization of Singletons The Singleton class that was presented before needed init to be idempotent. Changing its metaclass solves it: # Singleton classes are only init’ed once class Singleton(object): class __metaclass__(type): _initialized = set() def __call__(cls, *args, **kwargs): inits = Singleton.__metaclass__._initialized obj = cls.__new__(cls, *args, **kwargs) if isinstance(obj, cls) and cls not in inits: inits.add(cls) obj.__init__(*args, **kwargs) return obj _singletons = {} def __new__(cls, *args, **kwds): if cls not in cls._singletons: s = super(Singleton, cls) cls._singletons[cls] = super(Singleton, cls).__new__(cls, *args, **kwds) return cls._singletons[cls] J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 15 / 21
  • 60. More Examples Enforcing naming rules We don’t want classes with attributes that are not lowercase to be ever created !!!! class InvalidAttribName(TypeError): pass class MetaEnsureAttribNames(type): def __new__(mcl, name, bases, attrs): invalids = [attr for attr in attrs if not attr.islower()] if invalids: msg = quot;Invalid Attributes: quot; + quot;, quot;.join(invalids) raise InvalidAttribName, msg super_ = super(MetaEnsureAttribNames, mcl) return super_.__new__(mcl, name, bases, attrs) class EnsureAttribNames(object): __metaclass__ = MetaEnsureAttribNames (You can experiment with different rules for methods, rules for class names, etc.) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 16 / 21
  • 61. More Examples Enforcing naming rules We don’t want classes with attributes that are not lowercase to be ever created !!!! class InvalidAttribName(TypeError): pass class MetaEnsureAttribNames(type): def __new__(mcl, name, bases, attrs): invalids = [attr for attr in attrs if not attr.islower()] if invalids: msg = quot;Invalid Attributes: quot; + quot;, quot;.join(invalids) raise InvalidAttribName, msg super_ = super(MetaEnsureAttribNames, mcl) return super_.__new__(mcl, name, bases, attrs) class EnsureAttribNames(object): __metaclass__ = MetaEnsureAttribNames (You can experiment with different rules for methods, rules for class names, etc.) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 16 / 21
  • 62. More Examples Enforcing naming rules We don’t want classes with attributes that are not lowercase to be ever created !!!! class InvalidAttribName(TypeError): pass class MetaEnsureAttribNames(type): def __new__(mcl, name, bases, attrs): invalids = [attr for attr in attrs if not attr.islower()] if invalids: msg = quot;Invalid Attributes: quot; + quot;, quot;.join(invalids) raise InvalidAttribName, msg super_ = super(MetaEnsureAttribNames, mcl) return super_.__new__(mcl, name, bases, attrs) class EnsureAttribNames(object): __metaclass__ = MetaEnsureAttribNames (You can experiment with different rules for methods, rules for class names, etc.) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 16 / 21
  • 63. More Examples Checking Whether Interfaces are Implemented We want to extend python capabilities to respresent the idea of an interface and to ensure that a class that declares implementing one, actually does it Interfaces are represented by simple classes class IConnectable(object): def send(self, msg): pass def receive(self): pass Declaring an interface is done with a class’ attribute and is ensured by a metaclass class Channel(object): __metaclass__ = MetaInterfaceChecker __implements__ = IConnectable def send(self, msg): .... def receive(self): .... J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 17 / 21
  • 64. More Examples Checking Whether Interfaces are Implemented We want to extend python capabilities to respresent the idea of an interface and to ensure that a class that declares implementing one, actually does it Interfaces are represented by simple classes class IConnectable(object): def send(self, msg): pass def receive(self): pass Declaring an interface is done with a class’ attribute and is ensured by a metaclass class Channel(object): __metaclass__ = MetaInterfaceChecker __implements__ = IConnectable def send(self, msg): .... def receive(self): .... J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 17 / 21
  • 65. More Examples Checking Whether Interfaces are Implemented We want to extend python capabilities to respresent the idea of an interface and to ensure that a class that declares implementing one, actually does it Interfaces are represented by simple classes class IConnectable(object): def send(self, msg): pass def receive(self): pass Declaring an interface is done with a class’ attribute and is ensured by a metaclass class Channel(object): __metaclass__ = MetaInterfaceChecker __implements__ = IConnectable def send(self, msg): .... def receive(self): .... J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 17 / 21
  • 66. More Examples Checking Whether Interfaces are Implemented We want to extend python capabilities to respresent the idea of an interface and to ensure that a class that declares implementing one, actually does it Interfaces are represented by simple classes class IConnectable(object): def send(self, msg): pass def receive(self): pass Declaring an interface is done with a class’ attribute and is ensured by a metaclass class Channel(object): __metaclass__ = MetaInterfaceChecker __implements__ = IConnectable def send(self, msg): .... def receive(self): .... J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 17 / 21
  • 67. More Examples Checking Whether Interfaces are Implemented We want to extend python capabilities to respresent the idea of an interface and to ensure that a class that declares implementing one, actually does it Interfaces are represented by simple classes class IConnectable(object): def send(self, msg): pass def receive(self): pass Declaring an interface is done with a class’ attribute and is ensured by a metaclass class Channel(object): __metaclass__ = MetaInterfaceChecker __implements__ = IConnectable def send(self, msg): .... def receive(self): .... J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 17 / 21
  • 68. More Examples Checking Whether Interfaces are Implemented The following metaclass checks if all the methods in all declared interfaces are defined in the class (The implementation is na¨ so you can enhance it. hint: use module ıve, inspect) import set class InterfaceOmission(TypeError): pass class MetaInterfaceChecker(type): def __init__(cls, classname, bases, classdict): super(MetaInterfaceChecker, cls).__init__(classname, bases, classdict) cls_defines = set(dir(cls)) for interface in cls.__implements__: itf_requires = set(dir(interface)) if not itf_requires.issubset(cls_defines): raise (InterfaceOmission, list(itf_requires - cls_defines)) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 18 / 21
  • 69. More Examples Checking Whether Interfaces are Implemented The following metaclass checks if all the methods in all declared interfaces are defined in the class (The implementation is na¨ so you can enhance it. hint: use module ıve, inspect) import set class InterfaceOmission(TypeError): pass class MetaInterfaceChecker(type): def __init__(cls, classname, bases, classdict): super(MetaInterfaceChecker, cls).__init__(classname, bases, classdict) cls_defines = set(dir(cls)) for interface in cls.__implements__: itf_requires = set(dir(interface)) if not itf_requires.issubset(cls_defines): raise (InterfaceOmission, list(itf_requires - cls_defines)) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 18 / 21
  • 70. More Examples Checking Whether Interfaces are Implemented The following metaclass checks if all the methods in all declared interfaces are defined in the class (The implementation is na¨ so you can enhance it. hint: use module ıve, inspect) import set class InterfaceOmission(TypeError): pass class MetaInterfaceChecker(type): def __init__(cls, classname, bases, classdict): super(MetaInterfaceChecker, cls).__init__(classname, bases, classdict) cls_defines = set(dir(cls)) for interface in cls.__implements__: itf_requires = set(dir(interface)) if not itf_requires.issubset(cls_defines): raise (InterfaceOmission, list(itf_requires - cls_defines)) J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 18 / 21
  • 71. Concluding Remarks Conclusions Metaclasses must not be abused they put you dangerously near to the dark side if there’s a simple way to perform the same, don’t use them but sometimes they simplify things or lead to more efficient solutions But understanding them shows you the whole picture of python’s OO gives you new ways to think about solutions And they are fun !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 19 / 21
  • 72. Concluding Remarks Conclusions Metaclasses must not be abused they put you dangerously near to the dark side if there’s a simple way to perform the same, don’t use them but sometimes they simplify things or lead to more efficient solutions But understanding them shows you the whole picture of python’s OO gives you new ways to think about solutions And they are fun !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 19 / 21
  • 73. Concluding Remarks Conclusions Metaclasses must not be abused they put you dangerously near to the dark side if there’s a simple way to perform the same, don’t use them but sometimes they simplify things or lead to more efficient solutions But understanding them shows you the whole picture of python’s OO gives you new ways to think about solutions And they are fun !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 19 / 21
  • 74. Concluding Remarks Conclusions Metaclasses must not be abused they put you dangerously near to the dark side if there’s a simple way to perform the same, don’t use them but sometimes they simplify things or lead to more efficient solutions But understanding them shows you the whole picture of python’s OO gives you new ways to think about solutions And they are fun !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 19 / 21
  • 75. Concluding Remarks Conclusions Metaclasses must not be abused they put you dangerously near to the dark side if there’s a simple way to perform the same, don’t use them but sometimes they simplify things or lead to more efficient solutions But understanding them shows you the whole picture of python’s OO gives you new ways to think about solutions And they are fun !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 19 / 21
  • 76. Concluding Remarks Conclusions Metaclasses must not be abused they put you dangerously near to the dark side if there’s a simple way to perform the same, don’t use them but sometimes they simplify things or lead to more efficient solutions But understanding them shows you the whole picture of python’s OO gives you new ways to think about solutions And they are fun !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 19 / 21
  • 77. Concluding Remarks Conclusions Metaclasses must not be abused they put you dangerously near to the dark side if there’s a simple way to perform the same, don’t use them but sometimes they simplify things or lead to more efficient solutions But understanding them shows you the whole picture of python’s OO gives you new ways to think about solutions And they are fun !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 19 / 21
  • 78. Concluding Remarks Conclusions Metaclasses must not be abused they put you dangerously near to the dark side if there’s a simple way to perform the same, don’t use them but sometimes they simplify things or lead to more efficient solutions But understanding them shows you the whole picture of python’s OO gives you new ways to think about solutions And they are fun !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 19 / 21
  • 79. Concluding Remarks Conclusions Metaclasses must not be abused they put you dangerously near to the dark side if there’s a simple way to perform the same, don’t use them but sometimes they simplify things or lead to more efficient solutions But understanding them shows you the whole picture of python’s OO gives you new ways to think about solutions And they are fun !!! J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 19 / 21
  • 80. Bibliography Bibliography Shalahb Chaturvedi, Python Types and Objects Mike Fletcher, Metaclasses, Who, Why, When, Python Conference (Pycon) 2004. Ira R. Forman and Scott Danforth, Putting Metaclasses to Work. Addison-Wesley, 1999. Alex Martelli, Python in a Nutshell (2nd Edition), O’Reilly Media Inc, 2006. Alex Martelli, Python Metaclasses Alex Martelli, Anna Martelli, Python Cookbook (2nd Edition), O’Reilly Media Inc, 2005. The recipes are based on those in ActiveState Python Cookbook. David Mertz, A Primer on Python Metaclass Programming Guido Van Rossum, Unifying types and classes in Python 2.2 J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 20 / 21
  • 81. License License Aquesta obra est` subjecta a una llic`ncia Reconeixement-Compartir amb a e la mateixa llic`ncia 2.5 Espanya de Creative Commons. e Per veure’n una c`pia, visiteu o http://creativecommons.org/licenses/by-sa/2.5/es/ o envieu una carta a Creative Commons 559 Nathan Abbott Way Stanford California 94305 USA J.M.Gimeno (jmgimeno@diei.udl.cat) Metaclasses December 2008 21 / 21