Object-based inheritance in Python

T

Tobias Windeln

Hi!

I'm looking for suggestions on object-based inheritance
in Python. Automatic forwarding (often called delegation)
in Python is easy:

def __getattr__(self, attr):
return getattr(self.delegatee, attr)
def __setattr__(self, attr, value):
return setattr(self.delegatee, attr, value)

Maybe there is a way to hand over self to the delegatee object.
So the next call on self in the delegatee object is send to the child
object.

A small example:

class Child:
def __init__(self, delegatee):
self.__dict__['delegatee'] = delegatee

# TODO ... delegation/overriding mechanism ....

def m(self):
self.m2(self)
def m3(self):
print("Child")

class Delegatee:
def m2(self):
self.m3(self)
def m3(self):
print("Child")

#_______________________

The call to m2() is forwarded to the Delegatee.
The call to m3() in m2() is redirected to Child and
the m3() Method in Child is called:
=====================================================
m2(child_self)
child --------------------> delegatee
|
<-------------------|
m3(child_self)
=====================================================

This functionality would be helpfull in Patterns (Decorator, Strategy, etc.)

Do you have any suggestions on how to hand over self to the delegatee?
Since the first argument of every method in Python is self, the rest of
the object-based inheritance works automatically!

I usually work with Java, where I implemented this functionality with
enormous effort. When I saw Pythons reflective capabilities (__getattr__
etc.) I wondered if this is possible in an generic/easy way.


Thanks in advance
Tobias
 
S

Stephan Diehl

Tobias said:
Hi!

I'm looking for suggestions on object-based inheritance
in Python. Automatic forwarding (often called delegation)
in Python is easy:

Have a look at Hans Nowaks 'selfish' implementation:
http://zephyrfalcon.org/download/selfish-0.4.2.zip

This is a pythonesque interpretation of the 'self' language by Sun.
By the way, if you are googling, you want probably look for 'prototype based
languages'.
 
A

Alexander Schmolck

Tobias Windeln said:
Maybe there is a way to hand over self to the delegatee object. [...]

class Child:
def __init__(self, delegatee):
self.__dict__['delegatee'] = delegatee

Can't you just use this pattern:

self.__dict__['delegatee'] = delegatee(self)
?

'as
 
T

Tobias Windeln

Alexander said:
Maybe there is a way to hand over self to the delegatee object.
[...]


class Child:
def __init__(self, delegatee):
self.__dict__['delegatee'] = delegatee


Can't you just use this pattern:

self.__dict__['delegatee'] = delegatee(self)

This results in:
AttributeError: Delegatee instance has no __call__ method


Here is the solution by Hans Nowaks
(http://zephyrfalcon.org/download/selfish-0.4.2.zip):

##################################################################

import new
import types

__version__ = "0.4.2"
__author__ = "Hans Nowak"
__license__ = "python"
__cvsid__ = "$Id: selfish_v2.py,v 1.3 2003/09/22 04:30:50 hansn Exp $"

def rebind(method, obj):
return new.instancemethod(method.im_func, obj, obj.__class__)

class SelfObject:

def __init__(self):
pass

def __setattr__(self, name, value):
if name.endswith("_p"):
assert isinstance(value, SelfObject), \
"Only SelfObjects can be used for inheritance"
if isinstance(value, types.FunctionType):
m = new.instancemethod(value, self, self.__class__)
self.__dict__[name] = m
elif isinstance(value, types.UnboundMethodType):
self.__dict__[name] = rebind(value, self)
elif isinstance(value, types.MethodType):
self.__dict__[name] = rebind(value, self)
else:
self.__dict__[name] = value

def __getattr__(self, name):
if name in self.__dict__.keys():
# seems superfluous; if the attribute exists, __getattr__
# isn't called
return self.__dict__[name]
else:
# scan "ancestors" for this name...
# left-right based on name, depth first
items = self.__dict__.items()
items.sort()
for attrname, obj in items:
if attrname.endswith("_p"):
try:
z = obj.__getattr__(name)
except AttributeError:
pass
else:
if isinstance(z, types.MethodType):
z = rebind(z, self)
return z
raise AttributeError, name

Object = SelfObject()
 
H

Hung Jung Lu

Stephan Diehl said:
Have a look at Hans Nowaks 'selfish' implementation:
http://zephyrfalcon.org/download/selfish-0.4.2.zip

This is a pythonesque interpretation of the 'self' language by Sun.
By the way, if you are googling, you want probably look for 'prototype based
languages'.

Seems like prototype-based languages are catching up the attention of
people. I have looked at them recently. My feeling is that somehow
main development stopped around 1997. I have looked at Io (I know it's
born in 2002, but the ideas come from before), but I just get the
feeling that Io is not "clean" enough. Anyway, I think that instead of
designing final languages, it's a better idea to make *prototype*
languages (sorry for the pun) and experiment with various features.
One problem I've seen in Io is that they started to write software,
when the language itself is not well-defined yet. And so, you make
changes to the language, and you have to make corrections to large
body of existing code. And, also, once too much code is written with
existing language, it becomes really hard to make language changes
later: too much work to update legacy packages.

There are a few problems with current programming languages that only
come to bite you at large scale projects (Multiple Inheritance,
Metaprogramming, AOP, Multiple Version handling,
Transactional/Incremental programming with real-time rollback/undo,
ideas from Functional languages, etc.) And my experience has been that
the more complex your project becomes, the more you wish you had a
simple, clean, solid, powerful theoretical foundation for your
programming language. Prototype-based seems the right direction to go,
but I am kind of disappointed at all existing prototype-based
languages out there. Somehow something happened in 1997 that stopped
research in this direction. And now the prototype-based languages seem
so much behind. It's like time has been frozen for 6 years.

regards,

Hung Jung
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,175
Messages
2,570,942
Members
47,490
Latest member
Finplus

Latest Threads

Top