metaclass programming in python

81
Metaclass Programming in Python Advanced OO concepts Juan Manuel Gimeno Illa [email protected] December 2008 J.M.Gimeno ([email protected]) Metaclasses December 2008 1 / 21

Upload: juan-manuel-gimeno

Post on 19-May-2015

4.041 views

Category:

Education


4 download

DESCRIPTION

An introduction to metaclasses in python.

TRANSCRIPT

Page 1: Metaclass Programming in Python

Metaclass Programming in PythonAdvanced OO concepts

Juan Manuel Gimeno Illa

[email protected]

December 2008

J.M.Gimeno ([email protected]) Metaclasses December 2008 1 / 21

Page 2: Metaclass Programming in Python

This is dangerous, so don’t do it at home :-)

[Metaclasses] are deeper magic than 99% of users should everworry about. If you wonder whether you need them, you don’t(the people who actually need them know with certainty thatthey need them, and don’t need an explanation about why).

Tim Peters (c.l.p post 2002-12-22)

J.M.Gimeno ([email protected]) Metaclasses December 2008 2 / 21

Page 3: Metaclass Programming in Python

Outline

1 Basic Concepts

2 How classes are createdInside class statementMetaclass ProgrammingMetaclass Conflicts

3 More Examples

4 Concluding Remarks

J.M.Gimeno ([email protected]) Metaclasses December 2008 3 / 21

Page 4: Metaclass Programming in Python

Basic Concepts

Objects and Classes

Classes are templates used to create objectsI that share structure (attributes) and behaviour (methods)I 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 ofobj

(Sometimes type(type(obj)) is referred as the metaclass oftype(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 classesresides in the metaclass used to create the classes

(Note that the difference in metaclass can affect the objects of theclasses. For instance, instances of new-style classes behave differentlythan those of old-style ones)

J.M.Gimeno ([email protected]) Metaclasses December 2008 4 / 21

Page 5: Metaclass Programming in Python

Basic Concepts

Objects and Classes

Classes are templates used to create objectsI that share structure (attributes) and behaviour (methods)I 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 ofobj

(Sometimes type(type(obj)) is referred as the metaclass oftype(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 classesresides in the metaclass used to create the classes

(Note that the difference in metaclass can affect the objects of theclasses. For instance, instances of new-style classes behave differentlythan those of old-style ones)

J.M.Gimeno ([email protected]) Metaclasses December 2008 4 / 21

Page 6: Metaclass Programming in Python

Basic Concepts

Objects and Classes

Classes are templates used to create objectsI that share structure (attributes) and behaviour (methods)I 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 ofobj

(Sometimes type(type(obj)) is referred as the metaclass oftype(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 classesresides in the metaclass used to create the classes

(Note that the difference in metaclass can affect the objects of theclasses. For instance, instances of new-style classes behave differentlythan those of old-style ones)

J.M.Gimeno ([email protected]) Metaclasses December 2008 4 / 21

Page 7: Metaclass Programming in Python

Basic Concepts

Objects and Classes

Classes are templates used to create objectsI that share structure (attributes) and behaviour (methods)I 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 ofobj

(Sometimes type(type(obj)) is referred as the metaclass oftype(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 classesresides in the metaclass used to create the classes

(Note that the difference in metaclass can affect the objects of theclasses. For instance, instances of new-style classes behave differentlythan those of old-style ones)

J.M.Gimeno ([email protected]) Metaclasses December 2008 4 / 21

Page 8: Metaclass Programming in Python

Basic Concepts

Objects and Classes

Classes are templates used to create objectsI that share structure (attributes) and behaviour (methods)I 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 ofobj

(Sometimes type(type(obj)) is referred as the metaclass oftype(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 classesresides in the metaclass used to create the classes

(Note that the difference in metaclass can affect the objects of theclasses. For instance, instances of new-style classes behave differentlythan those of old-style ones)

J.M.Gimeno ([email protected]) Metaclasses December 2008 4 / 21

Page 9: Metaclass Programming in Python

Basic Concepts

Objects and Classes

Classes are templates used to create objectsI that share structure (attributes) and behaviour (methods)I 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 ofobj

(Sometimes type(type(obj)) is referred as the metaclass oftype(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 classesresides in the metaclass used to create the classes

(Note that the difference in metaclass can affect the objects of theclasses. For instance, instances of new-style classes behave differentlythan those of old-style ones)

J.M.Gimeno ([email protected]) Metaclasses December 2008 4 / 21

Page 10: Metaclass Programming in Python

Basic Concepts

Objects and Classes

Classes are templates used to create objectsI that share structure (attributes) and behaviour (methods)I 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 ofobj

(Sometimes type(type(obj)) is referred as the metaclass oftype(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 classesresides in the metaclass used to create the classes

(Note that the difference in metaclass can affect the objects of theclasses. For instance, instances of new-style classes behave differentlythan those of old-style ones)

J.M.Gimeno ([email protected]) Metaclasses December 2008 4 / 21

Page 11: Metaclass Programming in Python

Basic Concepts

Objects and Classes

Classes are templates used to create objectsI that share structure (attributes) and behaviour (methods)I 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 ofobj

(Sometimes type(type(obj)) is referred as the metaclass oftype(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 classesresides in the metaclass used to create the classes

(Note that the difference in metaclass can affect the objects of theclasses. For instance, instances of new-style classes behave differentlythan those of old-style ones)

J.M.Gimeno ([email protected]) Metaclasses December 2008 4 / 21

Page 12: Metaclass Programming in Python

Basic Concepts

Objects and Classes

Classes are templates used to create objectsI that share structure (attributes) and behaviour (methods)I 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 ofobj

(Sometimes type(type(obj)) is referred as the metaclass oftype(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 classesresides in the metaclass used to create the classes

(Note that the difference in metaclass can affect the objects of theclasses. For instance, instances of new-style classes behave differentlythan those of old-style ones)

J.M.Gimeno ([email protected]) Metaclasses December 2008 4 / 21

Page 13: Metaclass Programming in Python

Basic Concepts

New and Old Classes

>>> class New(object): pass...>>> class Old: pass...>>> n = New()>>> o = Old()>>> type(n)<class ’ main .New’>>>> type(o)<type ’instance’>>>> type(New)<type ’type’>>>> type(Old)<type ’classobj’>

Differences in new andold style objects (forinstance, the mro ofattributes) . . .

. . . are due to thedifferent metaclassesthey have

J.M.Gimeno ([email protected]) Metaclasses December 2008 5 / 21

Page 14: Metaclass Programming in Python

Basic Concepts

New and Old Classes

>>> class New(object): pass...>>> class Old: pass...>>> n = New()>>> o = Old()>>> type(n)<class ’ main .New’>>>> type(o)<type ’instance’>>>> type(New)<type ’type’>>>> type(Old)<type ’classobj’>

Differences in new andold style objects (forinstance, the mro ofattributes) . . .

. . . are due to thedifferent metaclassesthey have

J.M.Gimeno ([email protected]) Metaclasses December 2008 5 / 21

Page 15: Metaclass Programming in Python

Basic Concepts

New and Old Classes

>>> class New(object): pass...>>> class Old: pass...>>> n = New()>>> o = Old()>>> type(n)<class ’ main .New’>>>> type(o)<type ’instance’>>>> type(New)<type ’type’>>>> type(Old)<type ’classobj’>

Differences in new andold style objects (forinstance, the mro ofattributes) . . .

. . . are due to thedifferent metaclassesthey have

J.M.Gimeno ([email protected]) Metaclasses December 2008 5 / 21

Page 16: Metaclass Programming in Python

Basic Concepts

New and Old Classes

>>> class New(object): pass...>>> class Old: pass...>>> n = New()>>> o = Old()>>> type(n)<class ’ main .New’>>>> type(o)<type ’instance’>>>> type(New)<type ’type’>>>> type(Old)<type ’classobj’>

Differences in new andold style objects (forinstance, the mro ofattributes) . . .

. . . are due to thedifferent metaclassesthey have

J.M.Gimeno ([email protected]) Metaclasses December 2008 5 / 21

Page 17: Metaclass Programming in Python

Basic Concepts

New and Old Classes

>>> class New(object): pass...>>> class Old: pass...>>> n = New()>>> o = Old()>>> type(n)<class ’ main .New’>>>> type(o)<type ’instance’>>>> type(New)<type ’type’>>>> type(Old)<type ’classobj’>

Differences in new andold style objects (forinstance, the mro ofattributes) . . .

. . . are due to thedifferent metaclassesthey have

J.M.Gimeno ([email protected]) Metaclasses December 2008 5 / 21

Page 18: Metaclass Programming in Python

How classes are created Inside class statement

The built-in type

type(name, bases, attribs)(a.k.a types.TypeType) creates anew-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 withtheir 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, ...) anda dictionary containing the bindings created by the execution of thestatements.

J.M.Gimeno ([email protected]) Metaclasses December 2008 6 / 21

Page 19: Metaclass Programming in Python

How classes are created Inside class statement

The built-in type

type(name, bases, attribs)(a.k.a types.TypeType) creates anew-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 withtheir 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, ...) anda dictionary containing the bindings created by the execution of thestatements.

J.M.Gimeno ([email protected]) Metaclasses December 2008 6 / 21

Page 20: Metaclass Programming in Python

How classes are created Inside class statement

The built-in type

type(name, bases, attribs)(a.k.a types.TypeType) creates anew-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 withtheir 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, ...) anda dictionary containing the bindings created by the execution of thestatements.

J.M.Gimeno ([email protected]) Metaclasses December 2008 6 / 21

Page 21: Metaclass Programming in Python

How classes are created Inside class statement

The built-in type

type(name, bases, attribs)(a.k.a types.TypeType) creates anew-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 withtheir 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, ...) anda dictionary containing the bindings created by the execution of thestatements.

J.M.Gimeno ([email protected]) Metaclasses December 2008 6 / 21

Page 22: Metaclass Programming in Python

How classes are created Inside class statement

The built-in type

type(name, bases, attribs)(a.k.a types.TypeType) creates anew-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 withtheir 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, ...) anda dictionary containing the bindings created by the execution of thestatements.

J.M.Gimeno ([email protected]) Metaclasses December 2008 6 / 21

Page 23: Metaclass Programming in Python

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 = "Class1">>> class_bases = (object,)>>> class_dict = {}>>> class_body = """attrib = 1def __init__(self, n):

self.n = n""">>> exec class_body in globals(), class_dict>>> locals()[class_name] = type(class_name, class_bases, class_dict)

J.M.Gimeno ([email protected]) Metaclasses December 2008 7 / 21

Page 24: Metaclass Programming in Python

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 = "Class1">>> class_bases = (object,)>>> class_dict = {}>>> class_body = """attrib = 1def __init__(self, n):

self.n = n""">>> exec class_body in globals(), class_dict>>> locals()[class_name] = type(class_name, class_bases, class_dict)

J.M.Gimeno ([email protected]) Metaclasses December 2008 7 / 21

Page 25: Metaclass Programming in Python

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 = "Class1">>> class_bases = (object,)>>> class_dict = {}>>> class_body = """attrib = 1def __init__(self, n):

self.n = n""">>> exec class_body in globals(), class_dict>>> locals()[class_name] = type(class_name, class_bases, class_dict)

J.M.Gimeno ([email protected]) Metaclasses December 2008 7 / 21

Page 26: Metaclass Programming in Python

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 = "Class1">>> class_bases = (object,)>>> class_dict = {}>>> class_body = """attrib = 1def __init__(self, n):

self.n = n""">>> exec class_body in globals(), class_dict>>> locals()[class_name] = type(class_name, class_bases, class_dict)

J.M.Gimeno ([email protected]) Metaclasses December 2008 7 / 21

Page 27: Metaclass Programming in Python

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 intoa tuple t and executes the body in dictionary d

2 Then determines the metaclass to use for the new class object C1 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 classes3 If the current module has a global variable metaclass , then M is

the value of this variable4 Failing all of these, M defaults to types.ClassType, that is, an

old-style class is created

3 Finally, C = M(n, t, d)

1If the metaclasses of C’s bases’ do not form an inheritance lattice including its lowerbound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosingthis metatype conflict.

J.M.Gimeno ([email protected]) Metaclasses December 2008 8 / 21

Page 28: Metaclass Programming in Python

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 intoa tuple t and executes the body in dictionary d

2 Then determines the metaclass to use for the new class object C1 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 classes3 If the current module has a global variable metaclass , then M is

the value of this variable4 Failing all of these, M defaults to types.ClassType, that is, an

old-style class is created

3 Finally, C = M(n, t, d)

1If the metaclasses of C’s bases’ do not form an inheritance lattice including its lowerbound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosingthis metatype conflict.

J.M.Gimeno ([email protected]) Metaclasses December 2008 8 / 21

Page 29: Metaclass Programming in Python

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 intoa tuple t and executes the body in dictionary d

2 Then determines the metaclass to use for the new class object C1 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 classes3 If the current module has a global variable metaclass , then M is

the value of this variable4 Failing all of these, M defaults to types.ClassType, that is, an

old-style class is created

3 Finally, C = M(n, t, d)

1If the metaclasses of C’s bases’ do not form an inheritance lattice including its lowerbound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosingthis metatype conflict.

J.M.Gimeno ([email protected]) Metaclasses December 2008 8 / 21

Page 30: Metaclass Programming in Python

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 intoa tuple t and executes the body in dictionary d

2 Then determines the metaclass to use for the new class object C1 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 classes3 If the current module has a global variable metaclass , then M is

the value of this variable4 Failing all of these, M defaults to types.ClassType, that is, an

old-style class is created

3 Finally, C = M(n, t, d)

1If the metaclasses of C’s bases’ do not form an inheritance lattice including its lowerbound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosingthis metatype conflict.

J.M.Gimeno ([email protected]) Metaclasses December 2008 8 / 21

Page 31: Metaclass Programming in Python

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 intoa tuple t and executes the body in dictionary d

2 Then determines the metaclass to use for the new class object C1 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 classes3 If the current module has a global variable metaclass , then M is

the value of this variable4 Failing all of these, M defaults to types.ClassType, that is, an

old-style class is created

3 Finally, C = M(n, t, d)

1If the metaclasses of C’s bases’ do not form an inheritance lattice including its lowerbound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosingthis metatype conflict.

J.M.Gimeno ([email protected]) Metaclasses December 2008 8 / 21

Page 32: Metaclass Programming in Python

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 intoa tuple t and executes the body in dictionary d

2 Then determines the metaclass to use for the new class object C1 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 classes3 If the current module has a global variable metaclass , then M is

the value of this variable4 Failing all of these, M defaults to types.ClassType, that is, an

old-style class is created

3 Finally, C = M(n, t, d)

1If the metaclasses of C’s bases’ do not form an inheritance lattice including its lowerbound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosingthis metatype conflict.

J.M.Gimeno ([email protected]) Metaclasses December 2008 8 / 21

Page 33: Metaclass Programming in Python

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 intoa tuple t and executes the body in dictionary d

2 Then determines the metaclass to use for the new class object C1 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 classes3 If the current module has a global variable metaclass , then M is

the value of this variable4 Failing all of these, M defaults to types.ClassType, that is, an

old-style class is created

3 Finally, C = M(n, t, d)

1If the metaclasses of C’s bases’ do not form an inheritance lattice including its lowerbound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosingthis metatype conflict.

J.M.Gimeno ([email protected]) Metaclasses December 2008 8 / 21

Page 34: Metaclass Programming in Python

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 intoa tuple t and executes the body in dictionary d

2 Then determines the metaclass to use for the new class object C1 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 classes3 If the current module has a global variable metaclass , then M is

the value of this variable4 Failing all of these, M defaults to types.ClassType, that is, an

old-style class is created

3 Finally, C = M(n, t, d)

1If the metaclasses of C’s bases’ do not form an inheritance lattice including its lowerbound - i.e. if there is no leafmost metaclass - Python raises and exception diagnosingthis metatype conflict.

J.M.Gimeno ([email protected]) Metaclasses December 2008 8 / 21

Page 35: Metaclass Programming in Python

How classes are created Metaclass Programming

A very simple metaclass

Redefining method repr in class changes the way python show itsinstancesSo to change the way python shows a class, we redefine repr in themetaclass

>>> class MetaPretty(type):... def __repr__(cls):... return "I’m the class %s" % cls.__name__...>>> class Ugly: pass>>> Ugly<class ’__main__.Ugly’>>>> class Pretty(object):... __metaclass__ = MetaPretty>>> PrettyI’m the class Pretty

Metaclass programming is easier than you thought !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 9 / 21

Page 36: Metaclass Programming in Python

How classes are created Metaclass Programming

A very simple metaclass

Redefining method repr in class changes the way python show itsinstancesSo to change the way python shows a class, we redefine repr in themetaclass

>>> class MetaPretty(type):... def __repr__(cls):... return "I’m the class %s" % cls.__name__...>>> class Ugly: pass>>> Ugly<class ’__main__.Ugly’>>>> class Pretty(object):... __metaclass__ = MetaPretty>>> PrettyI’m the class Pretty

Metaclass programming is easier than you thought !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 9 / 21

Page 37: Metaclass Programming in Python

How classes are created Metaclass Programming

A very simple metaclass

Redefining method repr in class changes the way python show itsinstancesSo to change the way python shows a class, we redefine repr in themetaclass

>>> class MetaPretty(type):... def __repr__(cls):... return "I’m the class %s" % cls.__name__...>>> class Ugly: pass>>> Ugly<class ’__main__.Ugly’>>>> class Pretty(object):... __metaclass__ = MetaPretty>>> PrettyI’m the class Pretty

Metaclass programming is easier than you thought !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 9 / 21

Page 38: Metaclass Programming in Python

How classes are created Metaclass Programming

A very simple metaclass

Redefining method repr in class changes the way python show itsinstancesSo to change the way python shows a class, we redefine repr in themetaclass

>>> class MetaPretty(type):... def __repr__(cls):... return "I’m the class %s" % cls.__name__...>>> class Ugly: pass>>> Ugly<class ’__main__.Ugly’>>>> class Pretty(object):... __metaclass__ = MetaPretty>>> PrettyI’m the class Pretty

Metaclass programming is easier than you thought !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 9 / 21

Page 39: Metaclass Programming in Python

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 aremethods 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("_get_") or \name.startswith("_set_"))

for name in props:fget = getattr(cls, "_get_%s" % name, None)fset = getattr(cls, "_set_%s" % name, None)setattr(cls, name, property(fget, fset))

class AutoProp(object): __metaclass__ = MetaAutoPropclass UseX(AutoProp):

def __init__(self): self.__x = 0def _get_x(self): return self.__xdef _set_x(self, x): self.__x = x

J.M.Gimeno ([email protected]) Metaclasses December 2008 10 / 21

Page 40: Metaclass Programming in Python

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 aremethods 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("_get_") or \name.startswith("_set_"))

for name in props:fget = getattr(cls, "_get_%s" % name, None)fset = getattr(cls, "_set_%s" % name, None)setattr(cls, name, property(fget, fset))

class AutoProp(object): __metaclass__ = MetaAutoPropclass UseX(AutoProp):

def __init__(self): self.__x = 0def _get_x(self): return self.__xdef _set_x(self, x): self.__x = x

J.M.Gimeno ([email protected]) Metaclasses December 2008 10 / 21

Page 41: Metaclass Programming in Python

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 aremethods 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("_get_") or \name.startswith("_set_"))

for name in props:fget = getattr(cls, "_get_%s" % name, None)fset = getattr(cls, "_set_%s" % name, None)setattr(cls, name, property(fget, fset))

class AutoProp(object): __metaclass__ = MetaAutoPropclass UseX(AutoProp):

def __init__(self): self.__x = 0def _get_x(self): return self.__xdef _set_x(self, x): self.__x = x

J.M.Gimeno ([email protected]) Metaclasses December 2008 10 / 21

Page 42: Metaclass Programming in Python

How classes are created Metaclass Programming

Automatic property creation IIThe 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("_get_") or \

name.startswith("_set_"))for name in props:

fget = dict.get("_get_%s" % name)fset = dict.get("_set_%s" % name)dict[name] = property(fget, fset)

super_ = super(MetaAutoProp, mcl)return super_.__new__(mcl, classname, bases, dict)

class AutoProp(object): __metaclass__ = MetaAutoPropclass UseX(AutoProp):

def __init__(self): self.__x = 0def _get_x(self): return self.__xdef _set_x(self, x): self.__x = x

Deciding which way to go is not clearly defined

J.M.Gimeno ([email protected]) Metaclasses December 2008 11 / 21

Page 43: Metaclass Programming in Python

How classes are created Metaclass Programming

Automatic property creation IIThe 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("_get_") or \

name.startswith("_set_"))for name in props:

fget = dict.get("_get_%s" % name)fset = dict.get("_set_%s" % name)dict[name] = property(fget, fset)

super_ = super(MetaAutoProp, mcl)return super_.__new__(mcl, classname, bases, dict)

class AutoProp(object): __metaclass__ = MetaAutoPropclass UseX(AutoProp):

def __init__(self): self.__x = 0def _get_x(self): return self.__xdef _set_x(self, x): self.__x = x

Deciding which way to go is not clearly defined

J.M.Gimeno ([email protected]) Metaclasses December 2008 11 / 21

Page 44: Metaclass Programming in Python

How classes are created Metaclass Programming

Automatic property creation IIThe 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("_get_") or \

name.startswith("_set_"))for name in props:

fget = dict.get("_get_%s" % name)fset = dict.get("_set_%s" % name)dict[name] = property(fget, fset)

super_ = super(MetaAutoProp, mcl)return super_.__new__(mcl, classname, bases, dict)

class AutoProp(object): __metaclass__ = MetaAutoPropclass UseX(AutoProp):

def __init__(self): self.__x = 0def _get_x(self): return self.__xdef _set_x(self, x): self.__x = x

Deciding which way to go is not clearly defined

J.M.Gimeno ([email protected]) Metaclasses December 2008 11 / 21

Page 45: Metaclass Programming in Python

How classes are created Metaclass Programming

Automatic Initialization of Instance Attributesimport inspectclass 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_datasetattr(obj, attr, factory(*a, **k))

return objclass AutoAttr(object): __metaclass__ = MetaAutoAttrclass Recorder(AutoAttr):

count = 0 # is immutable so no shared among instancesevents = auto_attr(list)def record(self, event):

self.count += 1self.events.append((self.count, event))

J.M.Gimeno ([email protected]) Metaclasses December 2008 12 / 21

Page 46: Metaclass Programming in Python

How classes are created Metaclass Conflicts

But, sometimes, conflicts happen

Imagine one wants a class with both behaviours. If one tries:

from autoprop import AutoPropfrom autoattr import AutoAttr, auto_attrclass Both(AutoProp, AutoAttr):

__x = auto_attr(list)def _get_x(self): return self.__xdef _set_x(self, v): self.__x = v

One gets:

TypeError: Error when calling the metaclass basesmetaclass 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 bothbehaviours at the same time(This is the application of the Liskov Substitution Principle applied tometaclasses)

J.M.Gimeno ([email protected]) Metaclasses December 2008 13 / 21

Page 47: Metaclass Programming in Python

How classes are created Metaclass Conflicts

But, sometimes, conflicts happen

Imagine one wants a class with both behaviours. If one tries:

from autoprop import AutoPropfrom autoattr import AutoAttr, auto_attrclass Both(AutoProp, AutoAttr):

__x = auto_attr(list)def _get_x(self): return self.__xdef _set_x(self, v): self.__x = v

One gets:

TypeError: Error when calling the metaclass basesmetaclass 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 bothbehaviours at the same time(This is the application of the Liskov Substitution Principle applied tometaclasses)

J.M.Gimeno ([email protected]) Metaclasses December 2008 13 / 21

Page 48: Metaclass Programming in Python

How classes are created Metaclass Conflicts

But, sometimes, conflicts happen

Imagine one wants a class with both behaviours. If one tries:

from autoprop import AutoPropfrom autoattr import AutoAttr, auto_attrclass Both(AutoProp, AutoAttr):

__x = auto_attr(list)def _get_x(self): return self.__xdef _set_x(self, v): self.__x = v

One gets:

TypeError: Error when calling the metaclass basesmetaclass 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 bothbehaviours at the same time(This is the application of the Liskov Substitution Principle applied tometaclasses)

J.M.Gimeno ([email protected]) Metaclasses December 2008 13 / 21

Page 49: Metaclass Programming in Python

How classes are created Metaclass Conflicts

But, sometimes, conflicts happen

Imagine one wants a class with both behaviours. If one tries:

from autoprop import AutoPropfrom autoattr import AutoAttr, auto_attrclass Both(AutoProp, AutoAttr):

__x = auto_attr(list)def _get_x(self): return self.__xdef _set_x(self, v): self.__x = v

One gets:

TypeError: Error when calling the metaclass basesmetaclass 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 bothbehaviours at the same time(This is the application of the Liskov Substitution Principle applied tometaclasses)

J.M.Gimeno ([email protected]) Metaclasses December 2008 13 / 21

Page 50: Metaclass Programming in Python

How classes are created Metaclass Conflicts

But, sometimes, conflicts happen

Imagine one wants a class with both behaviours. If one tries:

from autoprop import AutoPropfrom autoattr import AutoAttr, auto_attrclass Both(AutoProp, AutoAttr):

__x = auto_attr(list)def _get_x(self): return self.__xdef _set_x(self, v): self.__x = v

One gets:

TypeError: Error when calling the metaclass basesmetaclass 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 bothbehaviours at the same time(This is the application of the Liskov Substitution Principle applied tometaclasses)

J.M.Gimeno ([email protected]) Metaclasses December 2008 13 / 21

Page 51: Metaclass Programming in Python

How classes are created Metaclass Conflicts

But, sometimes, conflicts happen

Imagine one wants a class with both behaviours. If one tries:

from autoprop import AutoPropfrom autoattr import AutoAttr, auto_attrclass Both(AutoProp, AutoAttr):

__x = auto_attr(list)def _get_x(self): return self.__xdef _set_x(self, v): self.__x = v

One gets:

TypeError: Error when calling the metaclass basesmetaclass 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 bothbehaviours at the same time(This is the application of the Liskov Substitution Principle applied tometaclasses)

J.M.Gimeno ([email protected]) Metaclasses December 2008 13 / 21

Page 52: Metaclass Programming in Python

How classes are created Metaclass Conflicts

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

from autoprop import MetaAutoPropfrom autoattr import MetaAutoAttr, auto_attrclass MetaBoth(MetaAutoAttr, MetaAutoProp): passclass Both(object):

__metaclass__ = MetaBoth__x = auto_attr(list)def _get_x(self):

return self.__xdef _set_x(self, value):

self.__x = value

(A recipe exists in the Python Cookbook that solves this problem by defininga metaclass factory method which creates the appropriate metaclass whenneeded)

J.M.Gimeno ([email protected]) Metaclasses December 2008 14 / 21

Page 53: Metaclass Programming in Python

How classes are created Metaclass Conflicts

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

from autoprop import MetaAutoPropfrom autoattr import MetaAutoAttr, auto_attrclass MetaBoth(MetaAutoAttr, MetaAutoProp): passclass Both(object):

__metaclass__ = MetaBoth__x = auto_attr(list)def _get_x(self):

return self.__xdef _set_x(self, value):

self.__x = value

(A recipe exists in the Python Cookbook that solves this problem by defininga metaclass factory method which creates the appropriate metaclass whenneeded)

J.M.Gimeno ([email protected]) Metaclasses December 2008 14 / 21

Page 54: Metaclass Programming in Python

How classes are created Metaclass Conflicts

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

from autoprop import MetaAutoPropfrom autoattr import MetaAutoAttr, auto_attrclass MetaBoth(MetaAutoAttr, MetaAutoProp): passclass Both(object):

__metaclass__ = MetaBoth__x = auto_attr(list)def _get_x(self):

return self.__xdef _set_x(self, value):

self.__x = value

(A recipe exists in the Python Cookbook that solves this problem by defininga metaclass factory method which creates the appropriate metaclass whenneeded)

J.M.Gimeno ([email protected]) Metaclasses December 2008 14 / 21

Page 55: Metaclass Programming in Python

How classes are created Metaclass Conflicts

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

from autoprop import MetaAutoPropfrom autoattr import MetaAutoAttr, auto_attrclass MetaBoth(MetaAutoAttr, MetaAutoProp): passclass Both(object):

__metaclass__ = MetaBoth__x = auto_attr(list)def _get_x(self):

return self.__xdef _set_x(self, value):

self.__x = value

(A recipe exists in the Python Cookbook that solves this problem by defininga metaclass factory method which creates the appropriate metaclass whenneeded)

J.M.Gimeno ([email protected]) Metaclasses December 2008 14 / 21

Page 56: Metaclass Programming in Python

How classes are created Metaclass Conflicts

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

from autoprop import MetaAutoPropfrom autoattr import MetaAutoAttr, auto_attrclass MetaBoth(MetaAutoAttr, MetaAutoProp): passclass Both(object):

__metaclass__ = MetaBoth__x = auto_attr(list)def _get_x(self):

return self.__xdef _set_x(self, value):

self.__x = value

(A recipe exists in the Python Cookbook that solves this problem by defininga metaclass factory method which creates the appropriate metaclass whenneeded)

J.M.Gimeno ([email protected]) Metaclasses December 2008 14 / 21

Page 57: Metaclass Programming in Python

How classes are created Metaclass Conflicts

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

from autoprop import MetaAutoPropfrom autoattr import MetaAutoAttr, auto_attrclass MetaBoth(MetaAutoAttr, MetaAutoProp): passclass Both(object):

__metaclass__ = MetaBoth__x = auto_attr(list)def _get_x(self):

return self.__xdef _set_x(self, value):

self.__x = value

(A recipe exists in the Python Cookbook that solves this problem by defininga metaclass factory method which creates the appropriate metaclass whenneeded)

J.M.Gimeno ([email protected]) Metaclasses December 2008 14 / 21

Page 58: Metaclass Programming in Python

More Examples

Avoiding multiple initialization of SingletonsThe Singleton class that was presented before needed init to beidempotent. Changing its metaclass solves it:

# Singleton classes are only init’ed onceclass Singleton(object):

class __metaclass__(type):_initialized = set()def __call__(cls, *args, **kwargs):

inits = Singleton.__metaclass__._initializedobj = 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 ([email protected]) Metaclasses December 2008 15 / 21

Page 59: Metaclass Programming in Python

More Examples

Avoiding multiple initialization of SingletonsThe Singleton class that was presented before needed init to beidempotent. Changing its metaclass solves it:

# Singleton classes are only init’ed onceclass Singleton(object):

class __metaclass__(type):_initialized = set()def __call__(cls, *args, **kwargs):

inits = Singleton.__metaclass__._initializedobj = 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 ([email protected]) Metaclasses December 2008 15 / 21

Page 60: Metaclass Programming in Python

More Examples

Enforcing naming rules

We don’t want classes with attributes that are not lowercase to be evercreated !!!!

class InvalidAttribName(TypeError): passclass MetaEnsureAttribNames(type):

def __new__(mcl, name, bases, attrs):invalids = [attr for attr in attrs

if not attr.islower()]if invalids:

msg = "Invalid Attributes: " + ", ".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 ([email protected]) Metaclasses December 2008 16 / 21

Page 61: Metaclass Programming in Python

More Examples

Enforcing naming rules

We don’t want classes with attributes that are not lowercase to be evercreated !!!!

class InvalidAttribName(TypeError): passclass MetaEnsureAttribNames(type):

def __new__(mcl, name, bases, attrs):invalids = [attr for attr in attrs

if not attr.islower()]if invalids:

msg = "Invalid Attributes: " + ", ".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 ([email protected]) Metaclasses December 2008 16 / 21

Page 62: Metaclass Programming in Python

More Examples

Enforcing naming rules

We don’t want classes with attributes that are not lowercase to be evercreated !!!!

class InvalidAttribName(TypeError): passclass MetaEnsureAttribNames(type):

def __new__(mcl, name, bases, attrs):invalids = [attr for attr in attrs

if not attr.islower()]if invalids:

msg = "Invalid Attributes: " + ", ".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 ([email protected]) Metaclasses December 2008 16 / 21

Page 63: Metaclass Programming in Python

More Examples

Checking Whether Interfaces are Implemented

We want to extend python capabilities to respresent the idea of an interfaceand to ensure that a class that declares implementing one, actually does itInterfaces are represented by simple classes

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

Declaring an interface is done with a class’ attribute and is ensured by ametaclass

class Channel(object):__metaclass__ = MetaInterfaceChecker__implements__ = IConnectabledef send(self, msg): ....def receive(self): ....

J.M.Gimeno ([email protected]) Metaclasses December 2008 17 / 21

Page 64: Metaclass Programming in Python

More Examples

Checking Whether Interfaces are Implemented

We want to extend python capabilities to respresent the idea of an interfaceand to ensure that a class that declares implementing one, actually does itInterfaces are represented by simple classes

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

Declaring an interface is done with a class’ attribute and is ensured by ametaclass

class Channel(object):__metaclass__ = MetaInterfaceChecker__implements__ = IConnectabledef send(self, msg): ....def receive(self): ....

J.M.Gimeno ([email protected]) Metaclasses December 2008 17 / 21

Page 65: Metaclass Programming in Python

More Examples

Checking Whether Interfaces are Implemented

We want to extend python capabilities to respresent the idea of an interfaceand to ensure that a class that declares implementing one, actually does itInterfaces are represented by simple classes

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

Declaring an interface is done with a class’ attribute and is ensured by ametaclass

class Channel(object):__metaclass__ = MetaInterfaceChecker__implements__ = IConnectabledef send(self, msg): ....def receive(self): ....

J.M.Gimeno ([email protected]) Metaclasses December 2008 17 / 21

Page 66: Metaclass Programming in Python

More Examples

Checking Whether Interfaces are Implemented

We want to extend python capabilities to respresent the idea of an interfaceand to ensure that a class that declares implementing one, actually does itInterfaces are represented by simple classes

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

Declaring an interface is done with a class’ attribute and is ensured by ametaclass

class Channel(object):__metaclass__ = MetaInterfaceChecker__implements__ = IConnectabledef send(self, msg): ....def receive(self): ....

J.M.Gimeno ([email protected]) Metaclasses December 2008 17 / 21

Page 67: Metaclass Programming in Python

More Examples

Checking Whether Interfaces are Implemented

We want to extend python capabilities to respresent the idea of an interfaceand to ensure that a class that declares implementing one, actually does itInterfaces are represented by simple classes

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

Declaring an interface is done with a class’ attribute and is ensured by ametaclass

class Channel(object):__metaclass__ = MetaInterfaceChecker__implements__ = IConnectabledef send(self, msg): ....def receive(self): ....

J.M.Gimeno ([email protected]) Metaclasses December 2008 17 / 21

Page 68: Metaclass Programming in Python

More Examples

Checking Whether Interfaces are Implemented

The following metaclass checks if all the methods in all declared interfaces aredefined in the class(The implementation is naıve, so you can enhance it. hint: use moduleinspect)

import setclass InterfaceOmission(TypeError): passclass 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 ([email protected]) Metaclasses December 2008 18 / 21

Page 69: Metaclass Programming in Python

More Examples

Checking Whether Interfaces are Implemented

The following metaclass checks if all the methods in all declared interfaces aredefined in the class(The implementation is naıve, so you can enhance it. hint: use moduleinspect)

import setclass InterfaceOmission(TypeError): passclass 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 ([email protected]) Metaclasses December 2008 18 / 21

Page 70: Metaclass Programming in Python

More Examples

Checking Whether Interfaces are Implemented

The following metaclass checks if all the methods in all declared interfaces aredefined in the class(The implementation is naıve, so you can enhance it. hint: use moduleinspect)

import setclass InterfaceOmission(TypeError): passclass 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 ([email protected]) Metaclasses December 2008 18 / 21

Page 71: Metaclass Programming in Python

Concluding Remarks

Conclusions

Metaclasses must not be abusedI they put you dangerously near to the dark sideI if there’s a simple way to perform the same, don’t use themI but sometimes they simplify thingsI or lead to more efficient solutions

But understanding themI shows you the whole picture of python’s OOI gives you new ways to think about solutions

And they are fun !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 19 / 21

Page 72: Metaclass Programming in Python

Concluding Remarks

Conclusions

Metaclasses must not be abusedI they put you dangerously near to the dark sideI if there’s a simple way to perform the same, don’t use themI but sometimes they simplify thingsI or lead to more efficient solutions

But understanding themI shows you the whole picture of python’s OOI gives you new ways to think about solutions

And they are fun !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 19 / 21

Page 73: Metaclass Programming in Python

Concluding Remarks

Conclusions

Metaclasses must not be abusedI they put you dangerously near to the dark sideI if there’s a simple way to perform the same, don’t use themI but sometimes they simplify thingsI or lead to more efficient solutions

But understanding themI shows you the whole picture of python’s OOI gives you new ways to think about solutions

And they are fun !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 19 / 21

Page 74: Metaclass Programming in Python

Concluding Remarks

Conclusions

Metaclasses must not be abusedI they put you dangerously near to the dark sideI if there’s a simple way to perform the same, don’t use themI but sometimes they simplify thingsI or lead to more efficient solutions

But understanding themI shows you the whole picture of python’s OOI gives you new ways to think about solutions

And they are fun !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 19 / 21

Page 75: Metaclass Programming in Python

Concluding Remarks

Conclusions

Metaclasses must not be abusedI they put you dangerously near to the dark sideI if there’s a simple way to perform the same, don’t use themI but sometimes they simplify thingsI or lead to more efficient solutions

But understanding themI shows you the whole picture of python’s OOI gives you new ways to think about solutions

And they are fun !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 19 / 21

Page 76: Metaclass Programming in Python

Concluding Remarks

Conclusions

Metaclasses must not be abusedI they put you dangerously near to the dark sideI if there’s a simple way to perform the same, don’t use themI but sometimes they simplify thingsI or lead to more efficient solutions

But understanding themI shows you the whole picture of python’s OOI gives you new ways to think about solutions

And they are fun !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 19 / 21

Page 77: Metaclass Programming in Python

Concluding Remarks

Conclusions

Metaclasses must not be abusedI they put you dangerously near to the dark sideI if there’s a simple way to perform the same, don’t use themI but sometimes they simplify thingsI or lead to more efficient solutions

But understanding themI shows you the whole picture of python’s OOI gives you new ways to think about solutions

And they are fun !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 19 / 21

Page 78: Metaclass Programming in Python

Concluding Remarks

Conclusions

Metaclasses must not be abusedI they put you dangerously near to the dark sideI if there’s a simple way to perform the same, don’t use themI but sometimes they simplify thingsI or lead to more efficient solutions

But understanding themI shows you the whole picture of python’s OOI gives you new ways to think about solutions

And they are fun !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 19 / 21

Page 79: Metaclass Programming in Python

Concluding Remarks

Conclusions

Metaclasses must not be abusedI they put you dangerously near to the dark sideI if there’s a simple way to perform the same, don’t use themI but sometimes they simplify thingsI or lead to more efficient solutions

But understanding themI shows you the whole picture of python’s OOI gives you new ways to think about solutions

And they are fun !!!

J.M.Gimeno ([email protected]) Metaclasses December 2008 19 / 21

Page 80: Metaclass Programming in Python

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 ([email protected]) Metaclasses December 2008 20 / 21

Page 81: Metaclass Programming in Python

License

License

Aquesta obra esta subjecta a una llicencia Reconeixement-Compartir ambla mateixa llicencia 2.5 Espanya de Creative Commons.Per veure’n una copia, visiteu

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

o envieu una carta a

Creative Commons559 Nathan Abbott WayStanfordCalifornia 94305USA

J.M.Gimeno ([email protected]) Metaclasses December 2008 21 / 21