Binding? problem

J

Josh English

I may not be using the language properly, but I suspect what I have is a
binding problem and I'm wondering if there's a better solution than
what I've come up with.

I'm working on a Stack based language that can import methods from
predefined libraries. Here's what I mean.
-------
class S:
def __init__(self,value):
self.value = value

def __repr__(self):
return '<%s>' % (self.__class__.__name__)

class Library:

### this method refers to 'self.s' which it isn't
### an attribute or method
def do_this(self):
self.s.value = 'this'


class Runner:
def __init__(self):
self.s = S('whock')

def __repr__(self):
return '<%s %s>' % (self.__class__.__name__,self.S)

def importmethod(self,obj):
#setattr(self,obj..__name__,obj.do_this)
self.do_this = obj.do_this

r = Runner()
print dir(r)

r.importmethod(Library)
r.do_this()
-----------
This basically all I want to do, but the last line raises an error
because the Library class has no attribute 's'. Right now my workaround
is to declare the do_this() method of the Library class:


def do_this(self,parent):
parent.s.value = 'this'

and use this in the Runner class:

def importmethod(self,obj):
setattr(self,'do_this',obj.do_this)
#self.do_this =getattr(obj,'do_this')

Is there a better way to do this?

Thanks,
Josh English
english-at-spiritone.com
 
S

Scott David Daniels

Josh said:
I'm working on a Stack based language that can import methods from
predefined libraries. Here's what I mean....
Tell us more about the problem you are trying to solve. Normally you'd
do this on classes. Why doesn't this work?:

class S(object):
def __init__(self, value):
self.value = value

def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.value)

class Mixin_do_this(object):
def do_this(self):
self.s.value = 'this'

class Runner(object):
def __init__(self):
self.s = S('whock')

def __repr__(self):
# self.s below, not self.S
return '<%s %s>' % (self.__class__.__name__, self.s)

class Runner2(Runner, Mixin_do_this): pass

r2 = Runner2()
print r2
r2.do_this()
print r2

-Scott David Daniels
(e-mail address removed)
 
J

Josh English

Scott said:
Tell us more about the problem you are trying to solve. Normally you'd
do this on classes. Why doesn't this work?:

What I want to do is have a class method that takes methods from one
class and applies them to the class instance, overriding the 'self' in
the method from the Library class to the Runner class. I'm looking for a
way to do this dynamic importing:

class Library:
... methods that have 'self' calls

r = Runner()
r.Import(Library)

r should now have the methods in the library.

Josh English
 
S

Scott David Daniels

Josh said:
What I want to do is have a class method that takes methods from one
class and applies them to the class instance, overriding the 'self' in
the method from the Library class to the Runner class.

There _is_ an issue of methods knowing what class they were bound in.
However, if you are willing to use staticmethod:

# Using curry (someday to show as functional.partial) as defined in:
# <http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549>
import new

def curry(*args, **okwargs):
assert args
if okwargs:
def curried(*iargs, **ikwargs):
if ikwargs:
kwargs = okwargs.copy()
kwargs.update(ikwargs)
else:
kwargs = okwargs
return args[0](*(args[1:] + iargs), **kwargs)
return curried

assert len(args) >= 2
if len(args) == 2:
return new.instancemethod(args[0], args[1], object)

if len(args) <= 1:
return args[0]
## The following runs in the wrong order
## return new.function(args[0].func_code,
## args[0].func_globals, argdefs=args[1:])
def scurried(*iargs, **kwargs):
return args[0](*(args[1:] + iargs), **kwargs)
return scurried

class S(object):
def __init__(self, value):
self.value = value

def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.value)

# Python 2.3 (and 2.2?) synax:
class Library(object):
# Cannot have "true" methods -- must be normal functions
def do_this(self):
self.s.value = 'this'
do_this = staticmethod(do_this)

# Python 2.4 syntax:
# class Library(object):
# # Cannot have "true" methods -- must be normal functions
# @staticmethod
# def do_this(self):
# self.s.value = 'this'

class Runner(object):
def __init__(self):
self.s = S('whock')

def imports(self, library):
for name in dir(library):
if not name.startswith('_'):
value = getattr(library, name)
if callable(value):
setattr(self, name, curry(value, self))

def __repr__(self):
return '<%s %s>' % (self.__class__.__name__, self.s)


-Scott David Daniels
(e-mail address removed)
 
J

Jeff Epler

I think that this program does what you want, with certain limitations.
It is related to the so-called Borg singleton pattern, in which all
(distinct) instances of a class have the same __dict__ so that they
appear to be identical. Here, all items in the "faux_mro" of a Runner
have the same dict as the Runner instance they serve, so when Library's
method executes it can access the "s" attribute.

I suspect that in the long run you'd be better off trying to solve your
problem in a less strange way, for instance by using the mix-in class
method suggested in an earlier message. Remember, you can use type()
or new.classobj() to create a class with given base types at run-time:
mixed_class = new.classobj("mixed", (base, mixin1, mixin2, ...), {})
mixed_instance = mixed_class()
Of course,
base = computed_base()
mixin1 = computed_mixin()
mixin2 = other_computed_mixin()
class mixed_class(base, mixin1, mixin2): pass
does the same thing.

class S:
def __init__(self,value):
self.value = value

def __repr__(self):
return '<%s: %r>' % (self.__class__.__name__, self.value)

class Library:

### this method refers to 'self.s' which it isn't
### an attribute or method
def do_this(self):
self.s.value = 'this'

class Runner:
def __init__(self):
self.s = S('whock')
self.faux_mro = []

def importmethod(self, cls):
inst = cls()
inst.__dict__ = self.__dict__
self.faux_mro.insert(-1, inst)

def __repr__(self):
return '<%s %s>' % (self.__class__.__name__,self.s)

def __getattr__(self, attr):
for item in self.faux_mro:
try:
return getattr(item, attr)
except AttributeError:
continue
raise AttributeError, ("Runner@%x nor its faux_mro has attribute %r"
% (id(self), attr))

r = Runner()
print dir(r)
print r
r.importmethod(Library)
r.do_this() # calls Library.do_this with self.__dict__ == r.__dict__
print r # r.s mutated

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFBRhwhJd01MZaTXX0RAkhnAKCDyxiN8ehO2M8DKg9y+9SZXiJ4BwCfUs30
57B1Hju1vu7YSJ1UHQT8On8=
=U3Wh
-----END PGP SIGNATURE-----
 
J

Josh English

Thanks for the help. I finally got a chance to play with this and I
think I can get it to work.

Josh English
 

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,206
Messages
2,571,069
Members
47,678
Latest member
Aniruddha Das

Latest Threads

Top