SlideShare a Scribd company logo
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

More Related Content

Similar to Metaclass Programming in Python

Metaclasses – Python’s Object-Oriented Paradigm and Its Metaprogramming
Metaclasses – Python’s Object-Oriented Paradigm and Its MetaprogrammingMetaclasses – Python’s Object-Oriented Paradigm and Its Metaprogramming
Metaclasses – Python’s Object-Oriented Paradigm and Its Metaprogramming
Inexture Solutions
 
Object oriented programming tutorial
Object oriented programming tutorialObject oriented programming tutorial
Object oriented programming tutorial
Ghulam Abbas Khan
 
L ab # 07
L ab # 07L ab # 07
L ab # 07Mr SMAK
 
IPP-M5-C1-Classes _ Objects python -S2.pptx
IPP-M5-C1-Classes _ Objects python -S2.pptxIPP-M5-C1-Classes _ Objects python -S2.pptx
IPP-M5-C1-Classes _ Objects python -S2.pptx
DhavalaShreeBJain
 
Class and object 1
Class and object 1Class and object 1
Class and object 1
sajib miha
 
Python data modelling
Python data modellingPython data modelling
Python data modelling
Ageeleshwar K
 
Python - object oriented
Python - object orientedPython - object oriented
Python - object oriented
Learnbay Datascience
 
OOP.pptx
OOP.pptxOOP.pptx
OOP.pptx
ashmitsen2005
 
Object Oriented Programming.pptx
Object Oriented Programming.pptxObject Oriented Programming.pptx
Object Oriented Programming.pptx
SAICHARANREDDYN
 
CLASS & OBJECT IN JAVA
CLASS & OBJECT  IN JAVACLASS & OBJECT  IN JAVA
CLASS & OBJECT IN JAVA
Riaj Uddin Mahi
 
OOSD1-unit1_1_16_09.pptx
OOSD1-unit1_1_16_09.pptxOOSD1-unit1_1_16_09.pptx
OOSD1-unit1_1_16_09.pptx
ShobhitSrivastava15887
 
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
danielt47
 
Python-Classes.pptx
Python-Classes.pptxPython-Classes.pptx
Python-Classes.pptx
Karudaiyar Ganapathy
 
Regex,functions, inheritance,class, attribute,overloding
Regex,functions, inheritance,class, attribute,overlodingRegex,functions, inheritance,class, attribute,overloding
Regex,functions, inheritance,class, attribute,overloding
sangumanikesh
 
Object Oriented Programming_Lecture 2
Object Oriented Programming_Lecture 2Object Oriented Programming_Lecture 2
Object Oriented Programming_Lecture 2
Mahmoud Alfarra
 
python.pptx
python.pptxpython.pptx
python.pptx
GayathriP95
 
Chapter 7 java
Chapter 7 javaChapter 7 java
Chapter 7 java
Ahmad sohail Kakar
 
Relationships and their representation in a class diagram.pptx
Relationships and their representation in a class diagram.pptxRelationships and their representation in a class diagram.pptx
Relationships and their representation in a class diagram.pptx
nesarahmad37
 
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
MohamedRamadan454985
 
Object in python tells about object oriented programming in python
Object in python tells about object oriented programming in pythonObject in python tells about object oriented programming in python
Object in python tells about object oriented programming in python
ReshmiShaw2
 

Similar to Metaclass Programming in Python (20)

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

More from Juan-Manuel Gimeno

Visualización de datos enlazados
Visualización de datos enlazadosVisualización de datos enlazados
Visualización de datos enlazados
Juan-Manuel Gimeno
 
Functional programming in clojure
Functional programming in clojureFunctional programming in clojure
Functional programming in clojure
Juan-Manuel Gimeno
 
Sistemas de recomendación
Sistemas de recomendaciónSistemas de recomendación
Sistemas de recomendación
Juan-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.0
Juan-Manuel Gimeno
 
Unicode (and Python)
Unicode (and Python)Unicode (and Python)
Unicode (and Python)
Juan-Manuel Gimeno
 
Object-oriented Programming in Python
Object-oriented Programming in PythonObject-oriented Programming in Python
Object-oriented Programming in Python
Juan-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 Style
Juan-Manuel Gimeno
 

More from 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
 

Recently uploaded

CACJapan - GROUP Presentation 1- Wk 4.pdf
CACJapan - GROUP Presentation 1- Wk 4.pdfCACJapan - GROUP Presentation 1- Wk 4.pdf
CACJapan - GROUP Presentation 1- Wk 4.pdf
camakaiclarkmusic
 
Model Attribute Check Company Auto Property
Model Attribute  Check Company Auto PropertyModel Attribute  Check Company Auto Property
Model Attribute Check Company Auto Property
Celine George
 
Pride Month Slides 2024 David Douglas School District
Pride Month Slides 2024 David Douglas School DistrictPride Month Slides 2024 David Douglas School District
Pride Month Slides 2024 David Douglas School District
David Douglas School District
 
"Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe..."Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe...
SACHIN R KONDAGURI
 
Guidance_and_Counselling.pdf B.Ed. 4th Semester
Guidance_and_Counselling.pdf B.Ed. 4th SemesterGuidance_and_Counselling.pdf B.Ed. 4th Semester
Guidance_and_Counselling.pdf B.Ed. 4th Semester
Atul Kumar Singh
 
BÀI TẬP BỔ TRỢ TIẾNG ANH GLOBAL SUCCESS LỚP 3 - CẢ NĂM (CÓ FILE NGHE VÀ ĐÁP Á...
BÀI TẬP BỔ TRỢ TIẾNG ANH GLOBAL SUCCESS LỚP 3 - CẢ NĂM (CÓ FILE NGHE VÀ ĐÁP Á...BÀI TẬP BỔ TRỢ TIẾNG ANH GLOBAL SUCCESS LỚP 3 - CẢ NĂM (CÓ FILE NGHE VÀ ĐÁP Á...
BÀI TẬP BỔ TRỢ TIẾNG ANH GLOBAL SUCCESS LỚP 3 - CẢ NĂM (CÓ FILE NGHE VÀ ĐÁP Á...
Nguyen Thanh Tu Collection
 
Operation Blue Star - Saka Neela Tara
Operation Blue Star   -  Saka Neela TaraOperation Blue Star   -  Saka Neela Tara
Operation Blue Star - Saka Neela Tara
Balvir Singh
 
STRAND 3 HYGIENIC PRACTICES.pptx GRADE 7 CBC
STRAND 3 HYGIENIC PRACTICES.pptx GRADE 7 CBCSTRAND 3 HYGIENIC PRACTICES.pptx GRADE 7 CBC
STRAND 3 HYGIENIC PRACTICES.pptx GRADE 7 CBC
kimdan468
 
Marketing internship report file for MBA
Marketing internship report file for MBAMarketing internship report file for MBA
Marketing internship report file for MBA
gb193092
 
special B.ed 2nd year old paper_20240531.pdf
special B.ed 2nd year old paper_20240531.pdfspecial B.ed 2nd year old paper_20240531.pdf
special B.ed 2nd year old paper_20240531.pdf
Special education needs
 
Lapbook sobre os Regimes Totalitários.pdf
Lapbook sobre os Regimes Totalitários.pdfLapbook sobre os Regimes Totalitários.pdf
Lapbook sobre os Regimes Totalitários.pdf
Jean Carlos Nunes Paixão
 
Multithreading_in_C++ - std::thread, race condition
Multithreading_in_C++ - std::thread, race conditionMultithreading_in_C++ - std::thread, race condition
Multithreading_in_C++ - std::thread, race condition
Mohammed Sikander
 
Francesca Gottschalk - How can education support child empowerment.pptx
Francesca Gottschalk - How can education support child empowerment.pptxFrancesca Gottschalk - How can education support child empowerment.pptx
Francesca Gottschalk - How can education support child empowerment.pptx
EduSkills OECD
 
Chapter -12, Antibiotics (One Page Notes).pdf
Chapter -12, Antibiotics (One Page Notes).pdfChapter -12, Antibiotics (One Page Notes).pdf
Chapter -12, Antibiotics (One Page Notes).pdf
Kartik Tiwari
 
Biological Screening of Herbal Drugs in detailed.
Biological Screening of Herbal Drugs in detailed.Biological Screening of Herbal Drugs in detailed.
Biological Screening of Herbal Drugs in detailed.
Ashokrao Mane college of Pharmacy Peth-Vadgaon
 
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
MysoreMuleSoftMeetup
 
The Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptxThe Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptx
DhatriParmar
 
The basics of sentences session 5pptx.pptx
The basics of sentences session 5pptx.pptxThe basics of sentences session 5pptx.pptx
The basics of sentences session 5pptx.pptx
heathfieldcps1
 
Unit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdfUnit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdf
Thiyagu K
 
MASS MEDIA STUDIES-835-CLASS XI Resource Material.pdf
MASS MEDIA STUDIES-835-CLASS XI Resource Material.pdfMASS MEDIA STUDIES-835-CLASS XI Resource Material.pdf
MASS MEDIA STUDIES-835-CLASS XI Resource Material.pdf
goswamiyash170123
 

Recently uploaded (20)

CACJapan - GROUP Presentation 1- Wk 4.pdf
CACJapan - GROUP Presentation 1- Wk 4.pdfCACJapan - GROUP Presentation 1- Wk 4.pdf
CACJapan - GROUP Presentation 1- Wk 4.pdf
 
Model Attribute Check Company Auto Property
Model Attribute  Check Company Auto PropertyModel Attribute  Check Company Auto Property
Model Attribute Check Company Auto Property
 
Pride Month Slides 2024 David Douglas School District
Pride Month Slides 2024 David Douglas School DistrictPride Month Slides 2024 David Douglas School District
Pride Month Slides 2024 David Douglas School District
 
"Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe..."Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe...
 
Guidance_and_Counselling.pdf B.Ed. 4th Semester
Guidance_and_Counselling.pdf B.Ed. 4th SemesterGuidance_and_Counselling.pdf B.Ed. 4th Semester
Guidance_and_Counselling.pdf B.Ed. 4th Semester
 
BÀI TẬP BỔ TRỢ TIẾNG ANH GLOBAL SUCCESS LỚP 3 - CẢ NĂM (CÓ FILE NGHE VÀ ĐÁP Á...
BÀI TẬP BỔ TRỢ TIẾNG ANH GLOBAL SUCCESS LỚP 3 - CẢ NĂM (CÓ FILE NGHE VÀ ĐÁP Á...BÀI TẬP BỔ TRỢ TIẾNG ANH GLOBAL SUCCESS LỚP 3 - CẢ NĂM (CÓ FILE NGHE VÀ ĐÁP Á...
BÀI TẬP BỔ TRỢ TIẾNG ANH GLOBAL SUCCESS LỚP 3 - CẢ NĂM (CÓ FILE NGHE VÀ ĐÁP Á...
 
Operation Blue Star - Saka Neela Tara
Operation Blue Star   -  Saka Neela TaraOperation Blue Star   -  Saka Neela Tara
Operation Blue Star - Saka Neela Tara
 
STRAND 3 HYGIENIC PRACTICES.pptx GRADE 7 CBC
STRAND 3 HYGIENIC PRACTICES.pptx GRADE 7 CBCSTRAND 3 HYGIENIC PRACTICES.pptx GRADE 7 CBC
STRAND 3 HYGIENIC PRACTICES.pptx GRADE 7 CBC
 
Marketing internship report file for MBA
Marketing internship report file for MBAMarketing internship report file for MBA
Marketing internship report file for MBA
 
special B.ed 2nd year old paper_20240531.pdf
special B.ed 2nd year old paper_20240531.pdfspecial B.ed 2nd year old paper_20240531.pdf
special B.ed 2nd year old paper_20240531.pdf
 
Lapbook sobre os Regimes Totalitários.pdf
Lapbook sobre os Regimes Totalitários.pdfLapbook sobre os Regimes Totalitários.pdf
Lapbook sobre os Regimes Totalitários.pdf
 
Multithreading_in_C++ - std::thread, race condition
Multithreading_in_C++ - std::thread, race conditionMultithreading_in_C++ - std::thread, race condition
Multithreading_in_C++ - std::thread, race condition
 
Francesca Gottschalk - How can education support child empowerment.pptx
Francesca Gottschalk - How can education support child empowerment.pptxFrancesca Gottschalk - How can education support child empowerment.pptx
Francesca Gottschalk - How can education support child empowerment.pptx
 
Chapter -12, Antibiotics (One Page Notes).pdf
Chapter -12, Antibiotics (One Page Notes).pdfChapter -12, Antibiotics (One Page Notes).pdf
Chapter -12, Antibiotics (One Page Notes).pdf
 
Biological Screening of Herbal Drugs in detailed.
Biological Screening of Herbal Drugs in detailed.Biological Screening of Herbal Drugs in detailed.
Biological Screening of Herbal Drugs in detailed.
 
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
 
The Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptxThe Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptx
 
The basics of sentences session 5pptx.pptx
The basics of sentences session 5pptx.pptxThe basics of sentences session 5pptx.pptx
The basics of sentences session 5pptx.pptx
 
Unit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdfUnit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdf
 
MASS MEDIA STUDIES-835-CLASS XI Resource Material.pdf
MASS MEDIA STUDIES-835-CLASS XI Resource Material.pdfMASS MEDIA STUDIES-835-CLASS XI Resource Material.pdf
MASS MEDIA STUDIES-835-CLASS XI Resource Material.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