Upload
guy-wiener
View
2.219
Download
1
Tags:
Embed Size (px)
Citation preview
Dynamic OOP and Meta-Classes in Python
Guy Wiener
Dept. of Applied Math and Computer ScienceWeizmann Institute for Science
24/5/2011
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 1 / 57
Introduction
Outline
1 Introduction
2 OOP Hacking
3 Meta-Classes
4 Examples
5 Summary
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 2 / 57
Introduction
What is OOP?
The OOP Manifest (abridged)Alan Kay, 1993
Everything is an object
Computation is performed by objects communicating with eachother by sending and receiving messages
Each object has its own memory (state), which consists of otherobjects.
Every object is an instance of a class.
The class is the repository for behavior. All instances of thesame class can perform the same actions.
Classes are organized into a singly rooted tree, called theinheritance hierarchy.
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 3 / 57
Introduction
What is an object?
An object, according to the OOP manifest:State Memory
Behavior Receiving and sending messages
Identity Each object is unique
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 4 / 57
Introduction
Objects Can Change!
Changing objectsState Read, write, add and remove field
Behavior Create, add and replace methods
Identity Remains the same
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 5 / 57
Introduction
Static Objects and Classes
Objects and Classes
Field descriptors
Method desc. and code
Hierarchy information
Class
Fieldscontent
ObjectRun-timetype infor-mation
Example
x: int
y: String
foo() {. . . }
goo() {. . . }
A
5
“hello”
Instance of A
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 6 / 57
Introduction
Dynamic Objects and Classes
Objects and Classes
A dictionaryof methodsand staticfields
Class
A dictionary offields and boundmethods
Object
Classpointer
Example
“foo” ⇒ {. . . }
“goo” ⇒ {. . . }
A
“x” ⇒ 5
“y” ⇒ “hello”
Instance of A
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 7 / 57
OOP Hacking
Outline
1 Introduction
2 OOP Hacking
3 Meta-Classes
4 Examples
5 Summary
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 8 / 57
OOP Hacking
Everything is a Dictionary
Python’s modules, classes and objects = Dictionaries.
The dictionary holds:Classes Methods and class variables
Objects Bound methods and fields
The “.” operator = Access the inner dictionary
The dir command = Lists keys of the inner dictionary
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 9 / 57
OOP Hacking
Manipulating the Inner Dictionary
The inner dictionary is accessible and manipulable by string keys!
Inner dictionary manipulationgetattr(o, ’a’) Get the attribute a from the dictionary of o
setattr(o, ’a’, v) Set the attribute a of o to be v
obj.foo is same as getattr(obj, ’foo’)
obj.foo = val is same as setattr(obj, ’foo’, val)
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 10 / 57
OOP Hacking
Manipulating the Inner Dictionary (cont’d)
Example>>> a = A()
>>> a.x = 5
>>> dir(a)
[..., ’x’]
>>> getattr(a, ’x’)
5
>>> setattr(a, ’x’, 6)
>>> a.x
6
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 11 / 57
OOP Hacking
Adding Fields
Adding fields to an objectclass A: pass
>>> a = A()
>>> a.x = 5
>>> a.x
5
>>> setattr(a, ’y’, 6)
>>> a.y
6
Gain & LossGained Flexible object content
Lost Type safety
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 12 / 57
OOP Hacking
Adding Fields
Adding fields to an objectclass A: pass
>>> a = A()
>>> a.x = 5
>>> a.x
5
>>> setattr(a, ’y’, 6)
>>> a.y
6
Gain & LossGained Flexible object content
Lost Type safety
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 12 / 57
OOP Hacking
Replacing Methods
Swapping methodsclass A:
def f(self):
print "f"
def g(self):
print "g"
>>> a = A()
>>> a.f, a.g = a.g, a.f
>>> a.f()
g
>>> a.g()
f
Gain & LossGained Change an object
behavior at runtime
Lost Control flow analysis
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 13 / 57
OOP Hacking
Replacing Methods
Swapping methodsclass A:
def f(self):
print "f"
def g(self):
print "g"
>>> a = A()
>>> a.f, a.g = a.g, a.f
>>> a.f()
g
>>> a.g()
f
Gain & LossGained Change an object
behavior at runtime
Lost Control flow analysis
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 13 / 57
OOP Hacking
Replacing Methods for a Class
Swapping class methodsclass A:
def f(self):
print "f"
def g(self):
print "g"
>>> a = A()
>>> A.f, A.g = A.g, A.f
>>> a.f()
g
>>> a.g()
f
Gain & LossGained Change a class at
runtime
Lost Sanity
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 14 / 57
OOP Hacking
Replacing Methods for a Class
Swapping class methodsclass A:
def f(self):
print "f"
def g(self):
print "g"
>>> a = A()
>>> A.f, A.g = A.g, A.f
>>> a.f()
g
>>> a.g()
f
Gain & LossGained Change a class at
runtime
Lost Sanity
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 14 / 57
OOP Hacking
Classes are Return Values Too
A function that returns a classdef PersonClass(salut):
class Person(object):
def __init__(self, name):
self.name = name
def greet(self):
print salut, self.name
return Person
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 15 / 57
OOP Hacking
Classes are Return Values Too (cont’d)
Making classesMan = PersonClass("Mr.")
Woman = PersonClass("Ms.")
Doctor = PersonClass("Dr.")
a = [Woman("Rose Tylar"),
Woman("Amy Pond"),
Man("Mickey Smith"),
Man("Rory Williams"),
Doctor("Who")]
Outputfor c in a: c.greet()
>>> Ms. Rose Tylar
Ms. Amy Pond
Mr. Mickey Smith
Mr. Rory Williams
Dr. Who
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 16 / 57
Meta-Classes
Outline
1 Introduction
2 OOP Hacking
3 Meta-Classes
4 Examples
5 Summary
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 17 / 57
Meta-Classes
What is Meta-Programming?
Meta-ProgramA program that:
One of its inputs is a program (possibly itself)
Its output is a program
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 18 / 57
Meta-Classes
What is Meta-OOP?
Meta-ClassA class that creates classes
Objects are instances of classes
Classes are objects
Classes are instances of meta-classes
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 19 / 57
Meta-Classes
Object Systems
3-levels
Object
A Class Type
super: Type[]
An Object
Legend
instance ofextends
4-levels
Object
Type
super: Type[]
A MetaClass
A Class
An Object
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 20 / 57
Meta-Classes Meta-Classes in Python
Outline
1 Introduction
2 OOP Hacking
3 Meta-ClassesMeta-Classes in Python
4 ExamplesLoggingCountingDelegationAssociations
5 Summary
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 21 / 57
Meta-Classes Meta-Classes in Python
Meta-Classes in Python
The type classBase class for meta-classes
Creates new classes
Dynamic members become static members of the instance class
type. init (cls, name, bases, dict)
cls The class object itself (i.e., “self”)
name The name of the class
bases A list of the base classes
dict A dictionary of the methods and static fields of the class
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 22 / 57
Meta-Classes Meta-Classes in Python
Creating Classes from Meta-Classes
Declaring a new class programatically# Meta-Class
class Printable(type):
def whoami(self): print "I am ", self.__name__
>>> Foo = Printable(’Foo’,(),{}) # Empty new class
>>> Foo.whoami()
I am Foo
>>> Foo.__class__
<class ’Printable’>
>>> f = Foo() # Object
>>> f.__class__
<class ’Foo’>
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 23 / 57
Meta-Classes Meta-Classes in Python
The metaclass field
Class C is an instance of a meta-class M if:1 C has a static field metaclass
2 One of the ancestors classes of C is an instance of M
3 There is a global variable metaclass
4 Otherwise, the default meta-class type is used
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 24 / 57
Meta-Classes Meta-Classes in Python
metaclass Example
Declaring a meta-class with metaclassclass Bar:
__metaclass__ = Printable
def foo(self): print ’foo’
>>> Bar.whoami()
I am a Bar
>>> b = Bar()
>>> b.foo()
foo
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 25 / 57
Examples
Outline
1 Introduction
2 OOP Hacking
3 Meta-Classes
4 Examples
5 Summary
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 26 / 57
Examples Logging
Outline
1 Introduction
2 OOP Hacking
3 Meta-ClassesMeta-Classes in Python
4 ExamplesLoggingCountingDelegationAssociations
5 Summary
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 27 / 57
Examples Logging
Logging with Meta-Classes
A logger decoratordef log(name, f):
def ret(*args):
print "enter", name
f(*args)
print "exit", name
return ret
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 28 / 57
Examples Logging
Logging with Meta-Classes (cont’d)
A logger meta-classclass Logged(type):
def init (cls, name, bases, dict):
type. init (cls, name, bases, dict)
p = re.compile(cls. logmatch )
for attr, item in dict.items():
if callable(item) and p.match(attr):
setattr(cls, attr, log(attr, item))
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 29 / 57
Examples Logging
Logging with Meta-Classes (cont’d)
A logged classclass Test:
metaclass = Logged
logmatch = ’.*’
def foo(self):
print ’foo’
>>> t = Test()
>>> t.foo()
enter foo
foo
exit foo
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 30 / 57
Examples Counting
Outline
1 Introduction
2 OOP Hacking
3 Meta-ClassesMeta-Classes in Python
4 ExamplesLoggingCountingDelegationAssociations
5 Summary
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 31 / 57
Examples Counting
Counting Instances
Countable meta-classclass Countable(type):
def new_init(cls, init):
def ret(self, *args):
init(self, *args)
cls.count = cls.count + 1
return ret
def __init__(cls, name, bases, dct):
type.__init__(cls, name, bases, dct)
cls.count = 0
cls.__init__ = cls.new_init(cls.__init__)
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 32 / 57
Examples Counting
Counting Example
Some classesclass Person:
__metaclass__ = Countable
def __init__(self, name):
self.name = name
class Book:
__metaclass__ = Countable
def __init__(self, name, author):
self.name = name
self.author = author
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 33 / 57
Examples Counting
Counting Example (cont’d)
Testingrah = Person("Robert Anson Heinlin")
b1 = Book("Stranger in a Strange Land", rah)
b2 = Book("Starship Troopers", rah)
print Person.count, Book.count
>>> 1 2
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 34 / 57
Examples Delegation
Outline
1 Introduction
2 OOP Hacking
3 Meta-ClassesMeta-Classes in Python
4 ExamplesLoggingCountingDelegationAssociations
5 Summary
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 35 / 57
Examples Delegation
Automatic Delegation
Delegate
An object of class A thatdispatches all message ofclass B to a target field oftype B.
Writing a delegate class is a monotonous work
But it can be done automatically
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 36 / 57
Examples Delegation
Delegation Using Meta-Classes
A delegation function decoratordef dlgt(cls, method):
def ret(self, *args):
method(self.__tgt__, *args)
return instancemethod(ret, None, cls)
instancemethod takes a function, an object/None and a class and
returns a method of the class
Auxiliary – Print class namedef clsname(self):
return self.__class__.__name__
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 37 / 57
Examples Delegation
Delegation Using Meta-Classes (cont’d)
The Delegate meta-classclass Delegate(type):
def __init__(cls, name, bases, dict):
type.__init__(cls, name, bases, dict)
tgtclass = cls.__tgtclass__
for name in dir(tgtclass):
val = getattr(tgtclass, name)
if callable(val):
setattr(cls, name, dlgt(cls, val))
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 38 / 57
Examples Delegation
Delegation Using Meta-Classes (cont’d)
The delegated classclass A:
def bar(self):
print clsname(self), ’bar’
def baz(self):
print clsname(self), ’baz’
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 39 / 57
Examples Delegation
Delegation Using Meta-Classes (cont’d)
The delegating classclass B:
metaclass = Delegate
tgtclass = A
def init (self, tgt):
self. tgt = tgt
def boo(self):
print clsname(self), ’boo’
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 40 / 57
Examples Delegation
Delegation Using Meta-Classes (cont’d)
Delegation test>>> b = B(A())
>>> b.bar()
A bar
>>> b.baz()
A baz
>>> b.boo()
B boo
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 41 / 57
Examples Delegation
Simplified Syntax for with Meta-Classes with Args.Thanks to Yoav Goldberg
Use a function to create the meta-classdef delegate_of(tgtclass):
class Delegate(type):
def __init__(cls, name, bases, dict):
type.__init__(cls, name, bases, dict)
for name in dir(tgtclass):
val = getattr(tgtclass, name)
if callable(val):
setattr(cls, name, dlgt(cls,val))
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 42 / 57
Examples Delegation
Simplified Syntax for Meta-Classes with Args.Thanks to Yoav Goldberg
Use the function to generate a meta-classclass B:
metaclass = delegate_of(A)
def init (self, tgt):
self. tgt = tgt
def boo(self):
print clsname(self), ’boo’
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 43 / 57
Examples Associations
Outline
1 Introduction
2 OOP Hacking
3 Meta-ClassesMeta-Classes in Python
4 ExamplesLoggingCountingDelegationAssociations
5 Summary
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 44 / 57
Examples Associations
Associations
A Bab
myA
0..m
myB
0..n
GoalsAggregation operations, like
a.getMyB().foreach().g()r = b.getMyA().filter().f().map().h()
Optimizations: Multithreading, caching
No textual code generation
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 45 / 57
Examples Associations
Basic Aggregation
Replace all public methods with an aggregator wrapperclass Aggr(type):
def __init__(cls, name, bases, dct):
p = re.compile(’__.*__’)
type.__init__(cls, name, bases, {})
for key, item in dct.iteritems():
if callable(item) and not p.match(key):
m = instancemethod(cls.wrap(item), None, self)
setattr(self, key, m)
def wrap(cls, func):
def ret(self, *args):
return self.__aggr__(func, *args)
return ret
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 46 / 57
Examples Associations
Basic Aggregation (cont’d)
Make aggrs. that extend impl and wrap ifce
class ListAggr(Aggr):
@staticmethod
def make(name, impl, ifce):
dct = {}
for key in dir(ifce):
dct[key] = getattr(ifce, key)
return ListAggr(name, (impl,), dct)
def __init__(self, name, bases, dct):
Aggr.__init__(self, name, bases, dct)
base = bases[0]
ctr = base.__init__ % Use impl’s constructor
self.__init__ = instancemethod(ctr, None, self)
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 47 / 57
Examples Associations
List-Based Sequential Aggrs.
Store list in private fieldclass ListFunc(object):
def __init__(self, data):
self.__data__ = data
def onAdd(self, other): pass
def onRemove(self, other): pass
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 48 / 57
Examples Associations
List-Based Sequential Aggrs. (cont’d)
Sequential Foreachclass ListSeqForeach(ListFunc):
def __init__(self, data):
ListFunc.__init__(self, data)
def __aggr__(self, func, *args):
for inst in self.__data__:
func(inst, *args)
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 49 / 57
Examples Associations
List-Based Sequential Aggrs. (cont’d)
Sequential Mapclass ListSeqMap(ListFunc):
def __init__(self, data):
ListFunc.__init__(self, data)
def __aggr__(self, func, *args):
ret = []
for inst in self.__data__:
ret.append(func(inst, *args))
return ret
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 50 / 57
Examples Associations
Binding It Together
Making an aggr. that extends seq. foreachdef makeForeachClass(cls):
return ListAggr.make(’...’, ListSeqForeach, cls)
ListFunc
ListSeqForeach
Aggr
ListAggr
ForeachClasscls
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 51 / 57
Examples Associations
Optimizations
Multithreaded Foreachclass ListSpawnForeach(ListFunc):
def __init__(self, data):
ListFunc.__init__(self, data)
def __aggr__(self, func, *args):
n = max(len(self.__data__)/K, 1)
ts = []
for c in chunks(self.__data__, n):
t = ForeachThread(c, func, args)
ts.append(t)
t.start()
for tr in ts: tr.join()
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 52 / 57
Examples Associations
Binding It Together, Multithreaded Version
Making an aggr. that extends parallel foreachdef makeForeachClass(cls):
return ListAggr.make(’...’, ListSpawnForeach, cls)
ListFunc
ListSpawnForeach
Aggr
ListAggr
ForeachClasscls
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 53 / 57
Examples Associations
Links
Download complete codehttp://www.cs.bgu.ac.il/~gwiener/software/associations/
Read full paper
Proceedings of ENASE’2010 / By request
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 54 / 57
Summary
Outline
1 Introduction
2 OOP Hacking
3 Meta-Classes
4 Examples
5 Summary
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 55 / 57
Summary
Advantages of Meta-Classes
Turn this. . .
Dai-U
ka-HakalTru-Saka-Uka
-Wek
uU
ru-N
ecro
s Phaarazu-Urha-Ytahi
Ia
Into this
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 56 / 57
Summary
Thank You!
Guy Wiener (WIS) Dynamic OOP and Meta-Classes in Python 24/5/2011 57 / 57