Mangle function name with decorator?

Adam adam.crossland at gmail.com
Wed Mar 18 11:18:56 EDT 2009


On Mar 18, 10:33 am, "J. Cliff Dyer" <j... at sdf.lonestar.org> wrote:
> You might be interested in redefining __getattribute__(self, attr) on
> your class.  This could operate in conjunction with the hash tables
> (dictionaries) mentioned by andrew cooke.  i.e. (untested code):
>
> class C(object):
>     def __init__(self):
>         self._get_table = {}
>         self._post_table = {}
>
>     def __getattribute__(self, x):
>         if self.method=='GET':
>             return object.__getattribute__(self, _get_table)[x]
>         elif self.method=='POST':
>             return object.__getattribute__(self, _post_table)[x]
>         else:
>             raise AttributeError
>     @GET
>     def foo(x):
>         return "Got", x
>     @POST
>     def foo(x)
>         return "Posted to", x
>
> This is definitely not functional code, but might get you in the right
> direction on __getattribute__.  __getattr__ might also work for you.  I
> haven't worked too much with these corners of python.
>
> Cheers,
> Cliff

Hey, Cliff.  Thanks for sharing this idea.  Unfortunately, providing a
way to actually call the method with the mangled name is relatively
easy, and there are options there.  The real issue, to me, seems to be
finding a way to prevent Python from eating all but the last version
of a function definition in a class.  While decorators are a elegant
and unintrusive approach, I don't believe that there is any way for a
decorator to collection information in a data structure and then
provide that data back to the class instance or the class's metaclass.

I'm beginning to think that I am trying to get the square peg of
Python to fit into the round hole of a .NET idiom.  I am trying to
borrow what I think is a really elegant and useful idiom from ASP.NET
MVC.  Specifically, in an ASP.NET MVC Controller class, I can have two
methods with the same name that are called for different HTTP Verbs by
applying an Attribute:

        public ActionResult Payment() {
            ViewData["Title"] = "Payment Information";
            ViewData["submit_text"] = "Next >";

            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Payment(FormCollection form) {

            return RedirectToAction("Legal");
        }

Right?  The first Payment method is called when the Payment page is
rendered.  The second is called when the form that it contains is
submitted.  I find it to be readable, elegant and it does not intrude
into the actual logic of the method itself.  The alternatives that I
can readily identify are less-than-optimal.  For instance, if could
just have an if statement inside the body of the method that branches
on the HTTP verb:

def Payment(self):
    if self.request.verb == 'GET':
        # Do stuff for GET
    elif self.request.verb == 'POST':
        # So stuff for POST

Yes, it would work, but it is ugly and requires me to mix in the same
function the behaviors for two very separate things.

Or, I could do something like this:

def GET_Payment(self):
    # Do stuff for GET

def POST_Payment(self):
    # Do stuff for POST

This is trivially-easy to implement (in this case, a metaclass can
very easily manipulate the namespace), but it makes the source code
less appealing and just feels crufty and hacky.  It also makes it
difficult to deal elegantly with having one method respond to more
than verb like I could if I could write:

@GET
@POST
def foo(self):
    # Do stuff for page foo, if it is GET or POST; PUT and DELETE not
allowed!





More information about the Python-list mailing list