473,224 Members | 1,564 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,224 software developers and data experts.

Automatic methods in new-style classes

Hey, I have the following code that has to send every command it
receives to a list of backends. Instead of:

class MultiBackend(object):
"""Renders to multiple backends"""

def __init__(self, backends):
self.backends = backends

def flush(self):
for b in self.backends:
b.flush()

def draw(self):
for b in self.backends:
b.draw()
I would like to write each method like:

flush = multimethod()

Is that possible using new-style classes?

Bert

Sep 29 '06 #1
6 1264
be******@yahoo.com wrote:
Hey, I have the following code that has to send every command it
receives to a list of backends. Instead of:

class MultiBackend(object):
"""Renders to multiple backends"""

def __init__(self, backends):
self.backends = backends

def flush(self):
for b in self.backends:
b.flush()

def draw(self):
for b in self.backends:
b.draw()
I would like to write each method like:

flush = multimethod()

Is that possible using new-style classes?
Not without a custom metaclass or the method name passed explicitly to
multimethod(). Here's a simpler approach that works with both new and
classic classes:

"""
>>class B(object):
.... def __init__(self, name):
.... self.name = name
.... def draw(self, x, y):
.... print "%s: draw(%s, %s)" % (self.name, x, y)
.... def flush(self):
.... print "%s: flush()" % self.name
>>m = MultiBackend([B("alpha"), B("beta")])
m.draw(1, 2)
alpha: draw(1, 2)
beta: draw(1, 2)
>>m.flush()
alpha: flush()
beta: flush()

"""

from operator import attrgetter

class MultiBackend(object):
def __init__(self, backends):
self._backends = backends
def __getattr__(self, name):
get = attrgetter(name)
def multi(self, *args, **kw):
for b in self._backends:
get(b)(*args, **kw)
setattr(self.__class__, name, multi)
return getattr(self, name)

if __name__ == "__main__":
import doctest
doctest.testmod()

Peter
Sep 29 '06 #2
be******@yahoo.com wrote:
Hey, I want to send commands to a list of backends:
How about something like:
class Forwards(object):

to_forward = set(['flush', 'read', 'write', 'close'])

def __init__(self, backends):
self.backends = backends

def forwarder(self, methodname):
def method(*args, **kwargs):
for b in self.backends:
getattr(b, methodname)(*args, **kwargs)
return forwarder

def __getattr__(self, name):
if name in self.to_forward:
return self.forwarder(name)
raise AttributeError("%r object has no attribute %r"
% (self.__class__.__name__, name))

--Scott David Daniels
sc***********@acm.org
Sep 29 '06 #3
Scott David Daniels wrote:
>
class Forwards(object):

to_forward = set(['flush', 'read', 'write', 'close'])

def __init__(self, backends):
self.backends = backends

def forwarder(self, methodname):
def method(*args, **kwargs):
for b in self.backends:
getattr(b, methodname)(*args, **kwargs)
return forwarder
^^^ return method # thinko.
>
def __getattr__(self, name):
if name in self.to_forward:
return self.forwarder(name)
raise AttributeError("%r object has no attribute %r"
% (self.__class__.__name__, name))
--Scott David Daniels
sc***********@acm.org
Sep 29 '06 #4
be******@yahoo.com wrote:
Hey, I have the following code that has to send every command it
receives to a list of backends.
<snip>
I would like to write each method like:

flush = multimethod()
Here's one way, using a metaclass:

class multimethod(object):
def transform(self, attr):
def dispatch(self, *args, **kw):
results = []
for b in self.backends:
results.append(getattr(b, attr)(*args, **kw))
return results
return dispatch

def multimethodmeta(name, bases, dict):
"""Transform each multimethod object into an actual method"""
for attr in dict:
if isinstance(dict[attr], multimethod):
dict[attr] = dict[attr].transform(attr)
return type(name, bases, dict)

class MultiBackend(object):
__metaclass__ = multimethodmeta
def __init__(self, backends):
self.backends = backends
add = multimethod()

class Foo(object):
def add(self, x, y):
print 'in Foo.add'
return x + y

class Bar(object):
def add(self, x, y):
print 'in Bar.add'
return str(x) + str(y)

m = MultiBackend([Foo(), Bar()])
print m.add(3, 4)

# Output:
in Foo.add
in Bar.add
[7, '34']

--Ben

Sep 29 '06 #5
Ben Cartwright wrote:
be******@yahoo.com wrote:
Hey, I have the following code that has to send every command it
receives to a list of backends.
<snip>
I would like to write each method like:

flush = multimethod()

Here's one way, using a metaclass:
Or if you don't mind a more verbose API, you may use a decorator
instead:

# comment out if version<2.5
from functools import wraps

def do_forall(attr):
def deco(func):
f_name = func.__name__
@wraps(func) # comment out if version<2.5
def wrapper(self,*args,**kwds):
for b in getattr(self,attr):
getattr(b,f_name)(*args,**kwds)
return wrapper
return deco

#====== Example =================================

class Foo(object):
def flush(self): print "Foo.flush"
def draw(self, x, y): print "Foo.draw(%s,%s)" % (x,y)

class Bar(object):
def flush(self): print "Bar.flush"
def draw(self, x, y): print "Bar.draw(%s,%s)" % (x,y)
forall_backends = do_forall('backends')

class MultiBackend(object):
"""Renders to multiple backends"""

def __init__(self, backends):
self.backends = backends

@forall_backends
def flush(self):
'Flush all backends'

@forall_backends
def draw(self, x, y):
'Draw point (x,y) on all backends'
m = MultiBackend([Foo(),Bar()])
m.flush()
m.draw(1,2)

#======================================

HTH,
George

Sep 30 '06 #6
The metaclass approach seems to be the one I was looking for. Thanks!

Bert

Sep 30 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: David Burson | last post by:
Hi, I have a VB.NET windows app that needs to automatically send a simple text email when my users run a new version of the app for the first time. I thought this would be simple, but after...
15
by: Kannan Goundan | last post by:
Maintaining a C++ header file can be painful. I want a way to automatically generate header files from the implementation file. Does anybody know of a program that does this? If not, I'd like...
5
by: Shane | last post by:
I wonder if someone has any ideas about the following. I am currently producing some reports for a manufacturing company who work with metal. A finished part can contain multiple sub-parts to...
3
by: Tom | last post by:
Using AccessXP with WindowsXP. I am creating a new database in Access2000 mode. The list of methods does not come up when I type a dot after a control in code. What do I need to do to turn that...
1
by: Michel Esber | last post by:
Hello, Linux RedHat AS4 running DB2 V8 FP11. I have followed the docs at http://tinyurl.com/qckrn and enabled automatic statistics collection. It has been 2 days since I updated my DB cfg and...
5
by: edd | last post by:
Hello all, Please consider: template<typename Tclass my_class; template<class my_class<int> { //... };
1
by: dev | last post by:
Hello, In VS2005, we have a WebService project (WSE) and a WebSite project (WSI) that uses WSE (we added the reference in the App_WebReferences of the WSI project) Is it possible to have the...
0
by: JoshforRefugee | last post by:
heard that we can do automatic code generation using macros, but not sure how can I pursue this. Here is my problem. In my env, I have class A,B and C. All of them has constructors, and few...
9
by: andrewfelch | last post by:
Hello all, I'm using the metaclass trick for automatic reloading of class member functions, found at: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/160164 My problem is that if I 1)...
3
by: myjish18 | last post by:
Hello, We have a DB2 UDB database v8.2.7 (db2 v8.2 fixpak 14) on AIX 5.3 which has Automatic Storage (AS) enabled. We want to disable automatic storage on entire database and/or disable...
1
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
0
by: veera ravala | last post by:
ServiceNow is a powerful cloud-based platform that offers a wide range of services to help organizations manage their workflows, operations, and IT services more efficiently. At its core, ServiceNow...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: mar23 | last post by:
Here's the situation. I have a form called frmDiceInventory with subform called subfrmDice. The subform's control source is linked to a query called qryDiceInventory. I've been trying to pick up the...
2
by: jimatqsi | last post by:
The boss wants the word "CONFIDENTIAL" overlaying certain reports. He wants it large, slanted across the page, on every page, very light gray, outlined letters, not block letters. I thought Word Art...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.