473,386 Members | 1,958 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,386 software developers and data experts.

Can I use decorators to manipulate return type or create methods?

I'm writing a class that will query a database for some data and return
the result to the caller. I need to be able to return the result of
the query in several different ways: list, xml, dictionary, etc. I was
wondering if I can use decorators to accomplish this.

For instance, I have the following method

def getUsers(self, params):
return users.query(dbc)

To get the appropriate return types, I also have these methods. I have
these convenience methods for every query method in my class.

def getUsersAsXML(self, params):
return self._toXML(self.getUsers(params))
def getUsersAsDict(self, params):
return self._toDict(self.getUsers(params))
def getUsersAsList(self, params):
return self._toList(self.getUsers(params))

Instead of creating these three methods for every query method, is
there a way to use decorators to manipulate the return type. I'd still
like to have the caller use getUsersAsXML, I just don't want to write
the AsXML methods for every query method. So the decorator would
essentially create the convenience methods instead of me coding them.

One solution that I don't want to use is passing a variable into the
query method that determines the return type. This is what I don't
want to do.
def getUsers(self, params, returnType):

Any ideas on how I can accomplish this?

thanks

Oct 19 '06 #1
8 1616
On 19 Oct 2006 06:43:49 -0700, WakeBdr <bb***@optiosoftware.comwrote:
I'm writing a class that will query a database for some data and return
the result to the caller. I need to be able to return the result of
the query in several different ways: list, xml, dictionary, etc. I was
wondering if I can use decorators to accomplish this.

For instance, I have the following method

def getUsers(self, params):
return users.query(dbc)

To get the appropriate return types, I also have these methods. I have
these convenience methods for every query method in my class.

def getUsersAsXML(self, params):
return self._toXML(self.getUsers(params))
def getUsersAsDict(self, params):
return self._toDict(self.getUsers(params))
def getUsersAsList(self, params):
return self._toList(self.getUsers(params))

Instead of creating these three methods for every query method, is
there a way to use decorators to manipulate the return type. I'd still
like to have the caller use getUsersAsXML, I just don't want to write
the AsXML methods for every query method. So the decorator would
essentially create the convenience methods instead of me coding them.

One solution that I don't want to use is passing a variable into the
query method that determines the return type. This is what I don't
want to do.
def getUsers(self, params, returnType):

Any ideas on how I can accomplish this?

You can't do it as fully magically as I'd like, because at the time
decorators are run, the methods are just functions and aren't bound as
methods yet (so you can't automagically add methods to the class, for
example - you'd need to do that after the class definition finishes
executing). You *could* decorate all the functions you want to have
special return types, then (after the class definition) loop through
those to generate the extra return funcs.

You can do it with a minimum of boilerplate this way:

from functools import wraps #only in 2.5, you can do this by hand in 2.4
#wrapped is the function we're calling and returning as XML
#xmlfunc is the stub function we're replacing
def returnXML(wrapped):
def f(xmlfunc):
@wraps(xmlfunc)
def xmlMethod(self):
return self.asXML(wrapped(self))
return xmlMethod
return f

class T(object):
def getUser(self):
return "user"
def asXML(self, data):
return "<xml>%s</xml>"%(data)
@returnXML(getUser)
def getUserAsXML(self):pass

t = T()
print t.getUserAsXML()
Oct 19 '06 #2
WakeBdr schrieb:
I'm writing a class that will query a database for some data and return
the result to the caller. I need to be able to return the result of
the query in several different ways: list, xml, dictionary, etc. I was
wondering if I can use decorators to accomplish this.

For instance, I have the following method

def getUsers(self, params):
return users.query(dbc)

To get the appropriate return types, I also have these methods. I have
these convenience methods for every query method in my class.

def getUsersAsXML(self, params):
return self._toXML(self.getUsers(params))
def getUsersAsDict(self, params):
return self._toDict(self.getUsers(params))
def getUsersAsList(self, params):
return self._toList(self.getUsers(params))

Instead of creating these three methods for every query method, is
there a way to use decorators to manipulate the return type. I'd still
like to have the caller use getUsersAsXML, I just don't want to write
the AsXML methods for every query method. So the decorator would
essentially create the convenience methods instead of me coding them.

One solution that I don't want to use is passing a variable into the
query method that determines the return type. This is what I don't
want to do.
def getUsers(self, params, returnType):

Any ideas on how I can accomplish this?
Use a metaclass.

class Magic(type):
def __new__(cls, name, bases, d):
for name, function in d.items():
try:
function._marked
def toXML(self, *args, **kwargs):
return self._toXML(function(self, *args, **kwargs))
def toFOO(self, *args, **kwargs):
return self._toFOO(function(self, *args, **kwargs))
d[name + "XML"] = toXML
d[name + "FOO"] = toFOO
except AttributeError:
pass
return type(name, bases, d)
def mark(f):
f._marked = True
return f

class MyClass(object):
__metaclass__ = Magic

def _toXML(self, value):
return "Look Ma, its XML! %r" % value

def _toFOO(self, value):
return "Look Ma, its FOO! %r" % value
@mark
def someMethod(self):
return "Its the data, son"
o = MyClass()

print o.someMethod()
print o.someMethodXML()
print o.someMethodFOO()

Diez
Oct 19 '06 #3
WakeBdr wrote:
I'm writing a class that will query a database for some data and return
the result to the caller. I need to be able to return the result of
the query in several different ways: list, xml, dictionary, etc. I was
wondering if I can use decorators to accomplish this.

For instance, I have the following method

def getUsers(self, params):
return users.query(dbc)

To get the appropriate return types, I also have these methods. I have
these convenience methods for every query method in my class.

def getUsersAsXML(self, params):
return self._toXML(self.getUsers(params))
def getUsersAsDict(self, params):
return self._toDict(self.getUsers(params))
def getUsersAsList(self, params):
return self._toList(self.getUsers(params))

Instead of creating these three methods for every query method, is
there a way to use decorators to manipulate the return type. I'd still
like to have the caller use getUsersAsXML, I just don't want to write
the AsXML methods for every query method. So the decorator would
essentially create the convenience methods instead of me coding them.

One solution that I don't want to use is passing a variable into the
query method that determines the return type. This is what I don't
want to do.
def getUsers(self, params, returnType):

Any ideas on how I can accomplish this?
Here's an odd approach, entirely based on naming conventions:

from operator import attrgetter

class Composer(object):
def __getattr__(self, name):
prefix, delim, suffix = name.rpartition("_as_")
if prefix and suffix:
cls = self.__class__
inner = attrgetter(prefix)
outer = attrgetter(delim + suffix)
def wrapped(self, *args):
return outer(self)(inner(self)(*args))
setattr(cls, name, wrapped)
return getattr(self, name)
raise AttributeError("sorry, no %r" % name)

class A(Composer):
def _as_xml(self, obj):
return "as_xml(%s)" % (obj,)
def _as_list(self, obj):
return "as_list(%s)" % (obj,)
def get_users(self):
return "get_users()"

class B(A):
def _as_list(self, obj):
return "AS_LIST(%s)" % (obj,)
def get_artist_as_a_young_man(self, name):
return "get_artist_as_a_young_man(name=%r)" % name

if __name__ == "__main__":
a = A()
b = B()
print a.get_users_as_list()
print b.get_users_as_list()
print a.get_users_as_xml()
print b.get_artist_as_a_young_man_as_xml("James")
print a.get_artist_as_a_young_man_as_xml("James") # AttributeError

Peter
Oct 19 '06 #4
Diez,
What does the function._marked accomplish?

Diez B. Roggisch wrote:
WakeBdr schrieb:
I'm writing a class that will query a database for some data and return
the result to the caller. I need to be able to return the result of
the query in several different ways: list, xml, dictionary, etc. I was
wondering if I can use decorators to accomplish this.

For instance, I have the following method

def getUsers(self, params):
return users.query(dbc)

To get the appropriate return types, I also have these methods. I have
these convenience methods for every query method in my class.

def getUsersAsXML(self, params):
return self._toXML(self.getUsers(params))
def getUsersAsDict(self, params):
return self._toDict(self.getUsers(params))
def getUsersAsList(self, params):
return self._toList(self.getUsers(params))

Instead of creating these three methods for every query method, is
there a way to use decorators to manipulate the return type. I'd still
like to have the caller use getUsersAsXML, I just don't want to write
the AsXML methods for every query method. So the decorator would
essentially create the convenience methods instead of me coding them.

One solution that I don't want to use is passing a variable into the
query method that determines the return type. This is what I don't
want to do.
def getUsers(self, params, returnType):

Any ideas on how I can accomplish this?

Use a metaclass.

class Magic(type):
def __new__(cls, name, bases, d):
for name, function in d.items():
try:
function._marked
def toXML(self, *args, **kwargs):
return self._toXML(function(self, *args, **kwargs))
def toFOO(self, *args, **kwargs):
return self._toFOO(function(self, *args, **kwargs))
d[name + "XML"] = toXML
d[name + "FOO"] = toFOO
except AttributeError:
pass
return type(name, bases, d)
def mark(f):
f._marked = True
return f

class MyClass(object):
__metaclass__ = Magic

def _toXML(self, value):
return "Look Ma, its XML! %r" % value

def _toFOO(self, value):
return "Look Ma, its FOO! %r" % value
@mark
def someMethod(self):
return "Its the data, son"
o = MyClass()

print o.someMethod()
print o.someMethodXML()
print o.someMethodFOO()

Diez
Oct 19 '06 #5
WakeBdr schrieb:
Diez,
What does the function._marked accomplish?
Its a decorator that tells the metaclass which functions to provide with
a *XML/*FOO variant as well. I thought that was pretty obvious, given
the name "mark" and all that.

Diez
Oct 19 '06 #6
Diez,
I get what that accomplishes now, but I'm having problems in my
implementation. I was able to write a standalone class that worked
correctly. However, in my code the class that I need to exhibit this
functionality inherits from another class. This seems to cause
problems when I attempt to implement you solution.

Let's say I have two classes that look like the following:

class Parent:
def getUsers(self, params):
raise 'Not implemented'

def _toXML(self, result):
return result.toXML()

def _toList(self, result):
return result.toList()

class Child(Parent):
def getUsers(self, params):
return users.query(dbc)
Caller object would say something like:
ch = Child()
ch.getUsersAsXML(params)

How would I implement your solution in this scenario. I've tried
"marking" the parent method, "marking" the child method, "marking"
both, but nothing seems to work.

WakeBdr wrote:
Diez,
What does the function._marked accomplish?

Diez B. Roggisch wrote:
WakeBdr schrieb:
I'm writing a class that will query a database for some data and return
the result to the caller. I need to be able to return the result of
the query in several different ways: list, xml, dictionary, etc. I was
wondering if I can use decorators to accomplish this.
>
For instance, I have the following method
>
def getUsers(self, params):
return users.query(dbc)
>
To get the appropriate return types, I also have these methods. I have
these convenience methods for every query method in my class.
>
def getUsersAsXML(self, params):
return self._toXML(self.getUsers(params))
def getUsersAsDict(self, params):
return self._toDict(self.getUsers(params))
def getUsersAsList(self, params):
return self._toList(self.getUsers(params))
>
Instead of creating these three methods for every query method, is
there a way to use decorators to manipulate the return type. I'd still
like to have the caller use getUsersAsXML, I just don't want to write
the AsXML methods for every query method. So the decorator would
essentially create the convenience methods instead of me coding them.
>
One solution that I don't want to use is passing a variable into the
query method that determines the return type. This is what I don't
want to do.
def getUsers(self, params, returnType):
>
Any ideas on how I can accomplish this?
Use a metaclass.

class Magic(type):
def __new__(cls, name, bases, d):
for name, function in d.items():
try:
function._marked
def toXML(self, *args, **kwargs):
return self._toXML(function(self, *args, **kwargs))
def toFOO(self, *args, **kwargs):
return self._toFOO(function(self, *args, **kwargs))
d[name + "XML"] = toXML
d[name + "FOO"] = toFOO
except AttributeError:
pass
return type(name, bases, d)
def mark(f):
f._marked = True
return f

class MyClass(object):
__metaclass__ = Magic

def _toXML(self, value):
return "Look Ma, its XML! %r" % value

def _toFOO(self, value):
return "Look Ma, its FOO! %r" % value
@mark
def someMethod(self):
return "Its the data, son"
o = MyClass()

print o.someMethod()
print o.someMethodXML()
print o.someMethodFOO()

Diez
Oct 20 '06 #7
WakeBdr schrieb:
Diez,
I get what that accomplishes now, but I'm having problems in my
implementation. I was able to write a standalone class that worked
correctly. However, in my code the class that I need to exhibit this
functionality inherits from another class. This seems to cause
problems when I attempt to implement you solution.
You need to give a __metaclass__ to one of them, and I think they must
be new-style-classes.
Diez
Oct 20 '06 #8
OK, I think I'm close now. I just can't get past this one error. Here
is my code, followed by the output produced when I run it.

class Magic(type):
def __new__(cls, name, bases, d):
for name, function in d.items():
try:
function._marked
print 'Class: %s' % cls
print 'Method: %s' % name
def toXML(self, *args, **kwargs):
return
self._toXML(function(self, *args, **kwargs))
def toList(self, *args, **kwargs):
return
self._toList(function(self, *args, **kwargs))
d[name+'XML'] = toXML
d[name+'List'] = toList
except AttributeError:
#traceback.print_exc()
pass
return type(name, bases, d)

def mark(f):
f._marked = True
return f

class test(object):

def _toXML(self, value):
return '<xml>%s</xml>' % value
def _toList(self, value):
return '<list>%s</list>' % value

class testtest(test):

__metaclass__ = Magic

@mark
def printData(self, data):
return 'child-%s' % data
t = testtest()
print t.printData('data')
print t.printDataXML('data')
print t.printDataList('data')

===========OUTPUT=========
Class: <class '__main__.Magic'>
Method: printData
child-data
Traceback (most recent call last):
File "test.py", line 43, in ?
print t.printDataXML('data')
File "test.py", line 11, in toXML
return self._toXML(function(self, *args, **kwargs))
TypeError: __new__() takes exactly 4 arguments (3 given)

Diez B. Roggisch wrote:
WakeBdr schrieb:
Diez,
I get what that accomplishes now, but I'm having problems in my
implementation. I was able to write a standalone class that worked
correctly. However, in my code the class that I need to exhibit this
functionality inherits from another class. This seems to cause
problems when I attempt to implement you solution.

You need to give a __metaclass__ to one of them, and I think they must
be new-style-classes.
Diez
Oct 20 '06 #9

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

Similar topics

4
by: Michael Sparks | last post by:
Anyway... At Europython Guido discussed with everyone the outstanding issue with decorators and there was a clear majority in favour of having them, which was good. From where I was sitting it...
1
by: Stephen Thorne | last post by:
Decorators have been getting lots of air-time at the moment, but only really the syntax. After a short discussion on irc the other night I decided to download python2.4 from experimental and write...
2
by: Guido van Rossum | last post by:
Robert and Python-dev, I've read the J2 proposal up and down several times, pondered all the issues, and slept on it for a night, and I still don't like it enough to accept it. The only reason...
0
by: Anthony Baxter | last post by:
To go along with the 2.4a3 release, here's an updated version of the decorator PEP. It describes the state of decorators as they are in 2.4a3. PEP: 318 Title: Decorators for Functions and...
3
by: Bruce Cropley | last post by:
Hi all I'm trying to generate test methods in a unittest TestCase subclass, using decorators. I'd like to be able to say: class MyTestCase(unittest.TestCase): @genTests(, , ) def...
1
by: birchb | last post by:
Guido has proposed a syntax for type annotations in Python-3000. Example: def foo(x: t1, y: t2) -> t3: ...body... http://www.artima.com/weblogs/viewpost.jsp?thread=87182 The types are...
5
by: bayerj | last post by:
I want to make a registry of methods of a class during creation. My attempt was this """ classdecorators.py Author: Justin Bayer Creation Date: 2006-06-22 Copyright (c) 2006 Chess Pattern...
2
by: Andrew West | last post by:
Probably a bit of weird question. I realise decorators shouldn't be executed until the function they are defined with are called, but is there anyway for me to find all the decorates declared in a...
0
by: Gabriel Genellina | last post by:
En Tue, 29 Jul 2008 08:45:02 -0300, Themis Bourdenas <bourdenas@gmail.com> escribi�: In a very strict sense, I'd say that all those references to "method decorators" are wrong - because...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.