Binding? problem

Jeff Epler jepler at unpythonic.net
Mon Sep 13 18:16:01 EDT 2004


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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20040913/f4395d4e/attachment.sig>


More information about the Python-list mailing list