Redundant code in multiple methods

bruno modulix onurb at xiludom.gro
Mon Sep 12 11:27:38 CEST 2005


Rob Conner wrote:
> No you don't need to know Zope to help me. The whole reason I'd even
> want to do this is because of Zope though. I made a Zope product, and
> now want to perfect it.
> 
> some simple example code...
> 
> <code>
> class User:
> 
>     def View(self):
>         # play with data here
>         myHtmlDoc = "pretend this is a uper profile"
>         return myHtmlDoc
>     index_html = View
> 
>     def Edit(self):
>         # play with data here
>         myHtmlDoc = "editing the user"
>         return myHtmlDoc
> </code>
> 
> So when visiting "website.com/User" zope will call User.index_html() or
> when you visit "website.com/User/View" zope will call User.View() In
> all of the testing/learning I've done on Zope I'm pretty sure that last
> item (index_html or View) must be a method,

Anything that returns HTML is ok. Can be a method, a data attribute, a
class attribute pointing to a ZPT or DTML file (like you do for ZMI
forms), and even any aquired component ! (the view and index_html
attributes doesnt need to live in the class...)

> 
> The problem comes when I want to have code put into every method.
> Perhaps a counter I want to increment on every visit to a User page.
> I can do this..
> 
> <snippet>
>     def View(self):
>         incrementCounter()
>         # play with data here
>         myHtmlDoc = "pretend this is a uper profile"
>         return myHtmlDoc
>     index_html = View
> 
>     def Edit(self):
>         incrementCounter()
>         # play with data here
>         myHtmlDoc = "editing the user"
>         return myHtmlDoc
> </snippet>
> 
> ... but in reality in my real code that one counter increment line ends
> up being 20 lines long. 

This is typically what AOP is all about - and Python offers a quite
usable support for "ad hoc" aspects, via the function wrapper idiom. The
simplest way is to use closures:

def wrapper(fun, wargs):
  def wrapped(fargs):
     do_something_before_funcall(wargs, fargs)
     res = fun(fargs)
     do_something_after_funcall(wargs, fargs)
     return res
  return wrapped

class Machin(object):
  def to_be_wrapped(self, args):
     # code here...
  # Zope 2.x uses Python 2.3.x, so no @decorator syntax
  to_be_wrapped = wrapper(to_be_wrapped, wargs)

If you need something more complex, see Sam's example with a callable
object.

(snip longer code exemple)


-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list