SlideShare una empresa de Scribd logo
1 de 81
Descargar para leer sin conexión
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

Más contenido relacionado

Similar a Metaclass Programming in Python

Object oriented programming tutorial
Object oriented programming tutorialObject oriented programming tutorial
Object oriented programming tutorialGhulam Abbas Khan
 
L ab # 07
L ab # 07L ab # 07
L ab # 07Mr SMAK
 
Class and object 1
Class and object 1Class and object 1
Class and object 1sajib miha
 
Python data modelling
Python data modellingPython data modelling
Python data modellingAgeeleshwar K
 
Object Oriented Programming.pptx
Object Oriented Programming.pptxObject Oriented Programming.pptx
Object Oriented Programming.pptxSAICHARANREDDYN
 
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.docxdanielt47
 
Object Oriented Programming_Lecture 2
Object Oriented Programming_Lecture 2Object Oriented Programming_Lecture 2
Object Oriented Programming_Lecture 2Mahmoud Alfarra
 
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.pptxnesarahmad37
 
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 pythonReshmiShaw2
 
Intro Ruby Classes Part I
Intro Ruby Classes Part IIntro Ruby Classes Part I
Intro Ruby Classes Part IJuan Leal
 

Similar a Metaclass Programming in Python (20)

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
 
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
 
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
 
Unit 3 Java
Unit 3 JavaUnit 3 Java
Unit 3 Java
 
Basic concept of Object Oriented Programming
Basic concept of Object Oriented Programming Basic concept of Object Oriented Programming
Basic concept of Object Oriented Programming
 
Intro Ruby Classes Part I
Intro Ruby Classes Part IIntro Ruby Classes Part I
Intro Ruby Classes Part I
 

Más de Juan-Manuel Gimeno

Visualización de datos enlazados
Visualización de datos enlazadosVisualización de datos enlazados
Visualización de datos enlazadosJuan-Manuel Gimeno
 
Functional programming in clojure
Functional programming in clojureFunctional programming in clojure
Functional programming in clojureJuan-Manuel Gimeno
 
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)Juan-Manuel Gimeno
 
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.0Juan-Manuel Gimeno
 
Object-oriented Programming in Python
Object-oriented Programming in PythonObject-oriented Programming in Python
Object-oriented Programming in PythonJuan-Manuel Gimeno
 
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 StyleJuan-Manuel Gimeno
 

Más de 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
 

Último

EDD8524 The Future of Educational Leader
EDD8524 The Future of Educational LeaderEDD8524 The Future of Educational Leader
EDD8524 The Future of Educational LeaderDr. Bruce A. Johnson
 
25 CHUYÊN ĐỀ ÔN THI TỐT NGHIỆP THPT 2023 – BÀI TẬP PHÁT TRIỂN TỪ ĐỀ MINH HỌA...
25 CHUYÊN ĐỀ ÔN THI TỐT NGHIỆP THPT 2023 – BÀI TẬP PHÁT TRIỂN TỪ ĐỀ MINH HỌA...25 CHUYÊN ĐỀ ÔN THI TỐT NGHIỆP THPT 2023 – BÀI TẬP PHÁT TRIỂN TỪ ĐỀ MINH HỌA...
25 CHUYÊN ĐỀ ÔN THI TỐT NGHIỆP THPT 2023 – BÀI TẬP PHÁT TRIỂN TỪ ĐỀ MINH HỌA...Nguyen Thanh Tu Collection
 
Metabolism , Metabolic Fate& disorders of cholesterol.pptx
Metabolism , Metabolic Fate& disorders of cholesterol.pptxMetabolism , Metabolic Fate& disorders of cholesterol.pptx
Metabolism , Metabolic Fate& disorders of cholesterol.pptxDr. Santhosh Kumar. N
 
Pharmacology chapter No 7 full notes.pdf
Pharmacology chapter No 7 full notes.pdfPharmacology chapter No 7 full notes.pdf
Pharmacology chapter No 7 full notes.pdfSumit Tiwari
 
How to Customise Quotation's Appearance Using PDF Quote Builder in Odoo 17
How to Customise Quotation's Appearance Using PDF Quote Builder in Odoo 17How to Customise Quotation's Appearance Using PDF Quote Builder in Odoo 17
How to Customise Quotation's Appearance Using PDF Quote Builder in Odoo 17Celine George
 
2024 March 11, Telehealth Billing- Current Telehealth CPT Codes & Telehealth ...
2024 March 11, Telehealth Billing- Current Telehealth CPT Codes & Telehealth ...2024 March 11, Telehealth Billing- Current Telehealth CPT Codes & Telehealth ...
2024 March 11, Telehealth Billing- Current Telehealth CPT Codes & Telehealth ...Marlene Maheu
 
The OERs: Transforming Education for Sustainable Future by Dr. Sarita Anand
The OERs: Transforming Education for Sustainable Future by Dr. Sarita AnandThe OERs: Transforming Education for Sustainable Future by Dr. Sarita Anand
The OERs: Transforming Education for Sustainable Future by Dr. Sarita AnandDr. Sarita Anand
 
Certification Study Group - Professional ML Engineer Session 3 (Machine Learn...
Certification Study Group - Professional ML Engineer Session 3 (Machine Learn...Certification Study Group - Professional ML Engineer Session 3 (Machine Learn...
Certification Study Group - Professional ML Engineer Session 3 (Machine Learn...gdgsurrey
 
Riti theory by Vamana Indian poetics.pptx
Riti theory by Vamana Indian poetics.pptxRiti theory by Vamana Indian poetics.pptx
Riti theory by Vamana Indian poetics.pptxDhatriParmar
 
VIT336 – Recommender System - Unit 3.pdf
VIT336 – Recommender System - Unit 3.pdfVIT336 – Recommender System - Unit 3.pdf
VIT336 – Recommender System - Unit 3.pdfArthyR3
 
2024.03.16 How to write better quality materials for your learners ELTABB San...
2024.03.16 How to write better quality materials for your learners ELTABB San...2024.03.16 How to write better quality materials for your learners ELTABB San...
2024.03.16 How to write better quality materials for your learners ELTABB San...Sandy Millin
 
Awards Presentation 2024 - March 12 2024
Awards Presentation 2024 - March 12 2024Awards Presentation 2024 - March 12 2024
Awards Presentation 2024 - March 12 2024bsellato
 
ASTRINGENTS.pdf Pharmacognosy chapter 5 diploma in Pharmacy
ASTRINGENTS.pdf Pharmacognosy chapter 5 diploma in PharmacyASTRINGENTS.pdf Pharmacognosy chapter 5 diploma in Pharmacy
ASTRINGENTS.pdf Pharmacognosy chapter 5 diploma in PharmacySumit Tiwari
 
DLL Catch Up Friday March 22.docx CATCH UP FRIDAYS
DLL Catch Up Friday March 22.docx CATCH UP FRIDAYSDLL Catch Up Friday March 22.docx CATCH UP FRIDAYS
DLL Catch Up Friday March 22.docx CATCH UP FRIDAYSTeacherNicaPrintable
 
POST ENCEPHALITIS case study Jitendra bhargav
POST ENCEPHALITIS case study  Jitendra bhargavPOST ENCEPHALITIS case study  Jitendra bhargav
POST ENCEPHALITIS case study Jitendra bhargavJitendra Bhargav
 
UNIT I Design Thinking and Explore.pptx
UNIT I  Design Thinking and Explore.pptxUNIT I  Design Thinking and Explore.pptx
UNIT I Design Thinking and Explore.pptxGOWSIKRAJA PALANISAMY
 
Dhavni Theory by Anandvardhana Indian Poetics
Dhavni Theory by Anandvardhana Indian PoeticsDhavni Theory by Anandvardhana Indian Poetics
Dhavni Theory by Anandvardhana Indian PoeticsDhatriParmar
 
THYROID HORMONE.pptx by Subham Panja,Asst. Professor, Department of B.Sc MLT,...
THYROID HORMONE.pptx by Subham Panja,Asst. Professor, Department of B.Sc MLT,...THYROID HORMONE.pptx by Subham Panja,Asst. Professor, Department of B.Sc MLT,...
THYROID HORMONE.pptx by Subham Panja,Asst. Professor, Department of B.Sc MLT,...Subham Panja
 
The First National K12 TUG March 6 2024.pdf
The First National K12 TUG March 6 2024.pdfThe First National K12 TUG March 6 2024.pdf
The First National K12 TUG March 6 2024.pdfdogden2
 

Último (20)

EDD8524 The Future of Educational Leader
EDD8524 The Future of Educational LeaderEDD8524 The Future of Educational Leader
EDD8524 The Future of Educational Leader
 
25 CHUYÊN ĐỀ ÔN THI TỐT NGHIỆP THPT 2023 – BÀI TẬP PHÁT TRIỂN TỪ ĐỀ MINH HỌA...
25 CHUYÊN ĐỀ ÔN THI TỐT NGHIỆP THPT 2023 – BÀI TẬP PHÁT TRIỂN TỪ ĐỀ MINH HỌA...25 CHUYÊN ĐỀ ÔN THI TỐT NGHIỆP THPT 2023 – BÀI TẬP PHÁT TRIỂN TỪ ĐỀ MINH HỌA...
25 CHUYÊN ĐỀ ÔN THI TỐT NGHIỆP THPT 2023 – BÀI TẬP PHÁT TRIỂN TỪ ĐỀ MINH HỌA...
 
Metabolism , Metabolic Fate& disorders of cholesterol.pptx
Metabolism , Metabolic Fate& disorders of cholesterol.pptxMetabolism , Metabolic Fate& disorders of cholesterol.pptx
Metabolism , Metabolic Fate& disorders of cholesterol.pptx
 
Pharmacology chapter No 7 full notes.pdf
Pharmacology chapter No 7 full notes.pdfPharmacology chapter No 7 full notes.pdf
Pharmacology chapter No 7 full notes.pdf
 
How to Customise Quotation's Appearance Using PDF Quote Builder in Odoo 17
How to Customise Quotation's Appearance Using PDF Quote Builder in Odoo 17How to Customise Quotation's Appearance Using PDF Quote Builder in Odoo 17
How to Customise Quotation's Appearance Using PDF Quote Builder in Odoo 17
 
2024 March 11, Telehealth Billing- Current Telehealth CPT Codes & Telehealth ...
2024 March 11, Telehealth Billing- Current Telehealth CPT Codes & Telehealth ...2024 March 11, Telehealth Billing- Current Telehealth CPT Codes & Telehealth ...
2024 March 11, Telehealth Billing- Current Telehealth CPT Codes & Telehealth ...
 
Least Significance Difference:Biostatics and Research Methodology
Least Significance Difference:Biostatics and Research MethodologyLeast Significance Difference:Biostatics and Research Methodology
Least Significance Difference:Biostatics and Research Methodology
 
The OERs: Transforming Education for Sustainable Future by Dr. Sarita Anand
The OERs: Transforming Education for Sustainable Future by Dr. Sarita AnandThe OERs: Transforming Education for Sustainable Future by Dr. Sarita Anand
The OERs: Transforming Education for Sustainable Future by Dr. Sarita Anand
 
Certification Study Group - Professional ML Engineer Session 3 (Machine Learn...
Certification Study Group - Professional ML Engineer Session 3 (Machine Learn...Certification Study Group - Professional ML Engineer Session 3 (Machine Learn...
Certification Study Group - Professional ML Engineer Session 3 (Machine Learn...
 
Riti theory by Vamana Indian poetics.pptx
Riti theory by Vamana Indian poetics.pptxRiti theory by Vamana Indian poetics.pptx
Riti theory by Vamana Indian poetics.pptx
 
VIT336 – Recommender System - Unit 3.pdf
VIT336 – Recommender System - Unit 3.pdfVIT336 – Recommender System - Unit 3.pdf
VIT336 – Recommender System - Unit 3.pdf
 
2024.03.16 How to write better quality materials for your learners ELTABB San...
2024.03.16 How to write better quality materials for your learners ELTABB San...2024.03.16 How to write better quality materials for your learners ELTABB San...
2024.03.16 How to write better quality materials for your learners ELTABB San...
 
Awards Presentation 2024 - March 12 2024
Awards Presentation 2024 - March 12 2024Awards Presentation 2024 - March 12 2024
Awards Presentation 2024 - March 12 2024
 
ASTRINGENTS.pdf Pharmacognosy chapter 5 diploma in Pharmacy
ASTRINGENTS.pdf Pharmacognosy chapter 5 diploma in PharmacyASTRINGENTS.pdf Pharmacognosy chapter 5 diploma in Pharmacy
ASTRINGENTS.pdf Pharmacognosy chapter 5 diploma in Pharmacy
 
DLL Catch Up Friday March 22.docx CATCH UP FRIDAYS
DLL Catch Up Friday March 22.docx CATCH UP FRIDAYSDLL Catch Up Friday March 22.docx CATCH UP FRIDAYS
DLL Catch Up Friday March 22.docx CATCH UP FRIDAYS
 
POST ENCEPHALITIS case study Jitendra bhargav
POST ENCEPHALITIS case study  Jitendra bhargavPOST ENCEPHALITIS case study  Jitendra bhargav
POST ENCEPHALITIS case study Jitendra bhargav
 
UNIT I Design Thinking and Explore.pptx
UNIT I  Design Thinking and Explore.pptxUNIT I  Design Thinking and Explore.pptx
UNIT I Design Thinking and Explore.pptx
 
Dhavni Theory by Anandvardhana Indian Poetics
Dhavni Theory by Anandvardhana Indian PoeticsDhavni Theory by Anandvardhana Indian Poetics
Dhavni Theory by Anandvardhana Indian Poetics
 
THYROID HORMONE.pptx by Subham Panja,Asst. Professor, Department of B.Sc MLT,...
THYROID HORMONE.pptx by Subham Panja,Asst. Professor, Department of B.Sc MLT,...THYROID HORMONE.pptx by Subham Panja,Asst. Professor, Department of B.Sc MLT,...
THYROID HORMONE.pptx by Subham Panja,Asst. Professor, Department of B.Sc MLT,...
 
The First National K12 TUG March 6 2024.pdf
The First National K12 TUG March 6 2024.pdfThe First National K12 TUG March 6 2024.pdf
The First National K12 TUG March 6 2024.pdf
 

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