Coding Style: Defining Functions within Methods?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Harry Pehkonen

    Coding Style: Defining Functions within Methods?

    I have been defining new class methods when I'm trying to simplify
    some code. But I'm thinking I should just define functions within
    that method because they aren't useful from the outside anyway.
    Example:


    Before:

    class Mess(object):
    def complicated(sel f, count):
    for i in count:
    self.do_loop(i)
    def do_loop(self, i):
    ...whatever...


    After:

    class Cleaner(object) :
    def complicated(sel f, count):
    def do_loop(i)
    ...whatever...
    for i in count:
    do_loop(i)

    The point is that do_loop is now not ``contaminating '' things. I
    suppose do_loop could be __do_loop, but it would still show up in
    places where I don't think it should (such as dir(Mess)).

    Thoughts?

    Thanks!
    Harry.
  • JCM

    #2
    Re: Coding Style: Defining Functions within Methods?

    Generally I also find it cleanest to push functions down into the most
    nested scope possible; it makes it clear that these are helper
    functions and not meant to be called externally.

    Harry Pehkonen <harry.pehkonen @hotpop.com> wrote:[color=blue]
    > I have been defining new class methods when I'm trying to simplify
    > some code. But I'm thinking I should just define functions within
    > that method because they aren't useful from the outside anyway.
    > Example:[/color]

    [color=blue]
    > Before:[/color]
    [color=blue]
    > class Mess(object):
    > def complicated(sel f, count):
    > for i in count:
    > self.do_loop(i)
    > def do_loop(self, i):
    > ...whatever...[/color]

    [color=blue]
    > After:[/color]
    [color=blue]
    > class Cleaner(object) :
    > def complicated(sel f, count):
    > def do_loop(i)
    > ...whatever...
    > for i in count:
    > do_loop(i)[/color]
    [color=blue]
    > The point is that do_loop is now not ``contaminating '' things. I
    > suppose do_loop could be __do_loop, but it would still show up in
    > places where I don't think it should (such as dir(Mess)).[/color]
    [color=blue]
    > Thoughts?[/color]
    [color=blue]
    > Thanks!
    > Harry.[/color]

    Comment

    • max

      #3
      Re: Coding Style: Defining Functions within Methods?

      JCM wrote:[color=blue]
      > Generally I also find it cleanest to push functions down into the most
      > nested scope possible; it makes it clear that these are helper
      > functions and not meant to be called externally.
      >[/color]
      I love this style and really miss it in other languages...
      my 2c.

      Comment

      • Eddie Corns

        #4
        Re: Coding Style: Defining Functions within Methods?

        harry.pehkonen@ hotpop.com (Harry Pehkonen) writes:
        [color=blue]
        >I have been defining new class methods when I'm trying to simplify
        >some code. But I'm thinking I should just define functions within
        >that method because they aren't useful from the outside anyway.
        >Example:[/color]

        [color=blue]
        >Before:[/color]
        [color=blue]
        >class Mess(object):
        > def complicated(sel f, count):
        > for i in count:
        > self.do_loop(i)
        > def do_loop(self, i):
        > ...whatever...[/color]

        [color=blue]
        >After:[/color]
        [color=blue]
        >class Cleaner(object) :
        > def complicated(sel f, count):
        > def do_loop(i)
        > ...whatever...
        > for i in count:
        > do_loop(i)[/color]
        [color=blue]
        >The point is that do_loop is now not ``contaminating '' things. I
        >suppose do_loop could be __do_loop, but it would still show up in
        >places where I don't think it should (such as dir(Mess)).[/color]
        [color=blue]
        >Thoughts?[/color]

        Definitely useful, especially as the inner function can see the same variables
        as the outer (though I do keep getting bitten when I expect to be able update
        variables).

        Eddie

        Comment

        • Bengt Richter

          #5
          Re: Coding Style: Defining Functions within Methods?

          On 5 Sep 2003 09:37:05 -0700, harry.pehkonen@ hotpop.com (Harry Pehkonen) wrote:
          [color=blue]
          >I have been defining new class methods when I'm trying to simplify
          >some code. But I'm thinking I should just define functions within
          >that method because they aren't useful from the outside anyway.
          >Example:
          >
          >
          >Before:
          >
          >class Mess(object):
          > def complicated(sel f, count):
          > for i in count:
          > self.do_loop(i)
          > def do_loop(self, i):
          > ...whatever...
          >
          >
          >After:
          >
          >class Cleaner(object) :
          > def complicated(sel f, count):
          > def do_loop(i)
          > ...whatever...
          > for i in count:
          > do_loop(i)
          >
          >The point is that do_loop is now not ``contaminating '' things. I
          >suppose do_loop could be __do_loop, but it would still show up in
          >places where I don't think it should (such as dir(Mess)).
          >
          >Thoughts?[/color]

          I like defining nested functions except for the fact that a definition is executable code
          in itself, and will be re-executed each time the outer function or method is called. I'm
          not sure how long MAKE_FUNCTION or MAKE_CLOSURE take to execute, but IWT it must mean allocating
          and glueing together the dynamic elements necessary for a distinct function/closure instance,
          and then disposing of them at some point on/after their going out of scope, vs. e.g. just locating
          a sibling method.

          OTOH, the outer overhead may become relatively insignificant if the inner is called boocoo times
          in a loop and/or recursively.

          On the third hand, clear code will outweigh any performance issues for much code.

          Regards,
          Bengt Richter

          Comment

          • Anton Vredegoor

            #6
            Re: Coding Style: Defining Functions within Methods?

            harry.pehkonen@ hotpop.com (Harry Pehkonen) wrote:
            [color=blue]
            >I have been defining new class methods when I'm trying to simplify
            >some code. But I'm thinking I should just define functions within
            >that method because they aren't useful from the outside anyway.[/color]

            It's also possible to generate classes by using a factory function.
            For an example of it getting a bit out of control see the code below.

            Anton

            ---

            from __future__ import division
            from Tkinter import *

            def template(x=None ):
            class T(tuple):
            def __new__(cls, *args):
            return tuple.__new__(c ls, args)
            def geta(self): return self[0]
            def getb(self): return self[1]
            a,b = map(property,[geta,getb])
            return T

            Point = template()
            Rect = template(Point)
            Cube = template(Rect)

            class Transformer(Cub e):

            def __init__(self, *args):
            a,b = self.a,self.b
            fx = (b.b.a-b.a.a)/(a.b.a-a.a.a)
            fy = (b.b.b-b.a.b)/(a.b.b-a.a.b)
            f = min(fx,fy)
            wxc = (a.a.a+a.b.a)/2
            wyc = (a.a.b+a.b.b)/2
            vxc = (b.a.a+b.b.a)/2
            vyc = (b.a.b+b.b.b)/2
            xc = vxc-f*wxc
            yc = vyc-f*wyc
            self.f,self.xc, self.yc = f,xc,yc

            def transform(self, R):
            f,xc,yc = self.f,self.xc, self.yc
            p1 = Point(f*R.a.a+x c, f*R.a.b+yc)
            p2 = Point(f*R.b.a+x c, f*R.b.b+yc)
            return Rect(p1,p2)

            class Cartesian:

            def __init__(self, master):
            self.canvas = Canvas(master,w idth=500,height =500)
            self.canvas.pac k(fill= BOTH, expand=YES)
            master.bind("<E scape>", lambda event='ignored' ,
            m=master: m.destroy())
            master.bind("<C onfigure>", self.configure)

            def configure(self, event):
            self.draw()

            def draw(self):
            c = self.canvas
            c.delete('all')
            T = Transformer(sel f.b,self.a)
            colors ='Red Green Blue Magenta Cyan Yellow'.split()
            for i in range(50,0,-1):
            R = Rect(Point(-i,-i),Point(i,i))
            c.create_rectan gle(T.transform (R),
            fill=colors[(i-1)%len(colors)])

            def geta(self):
            c = self.canvas
            p1 = Point(0,0)
            p2 = Point(c.winfo_w idth(), c.winfo_height( ))
            return Rect(p1,p2)

            def getb(self):
            a = 50
            p1 = Point(-a,-a)
            p2 = Point(a,a)
            return Rect(p1,p2)

            a,b = map(property,[geta,getb])

            def main():
            root = Tk()
            ca = Cartesian(root)
            root.mainloop()

            if __name__=='__ma in__':
            main()





            Comment

            • JCM

              #7
              Re: Coding Style: Defining Functions within Methods?

              Bengt Richter <bokr@oz.net> wrote:[color=blue]
              > I like defining nested functions except for the fact that a definition is executable code
              > in itself, and will be re-executed each time the outer function or method is called. I'm
              > not sure how long MAKE_FUNCTION or MAKE_CLOSURE take to execute, but IWT it must mean allocating
              > and glueing together the dynamic elements necessary for a distinct function/closure instance,
              > and then disposing of them at some point on/after their going out of scope, vs. e.g. just locating
              > a sibling method.[/color]

              This doesn't need to be slow--it's up to the implementation to try
              to be as smart as possible. A compiler can do lambda-lifting to
              transform a program with nested functions to one without, so there
              really is nothing inherently slow about nested functions.

              Comment

              • Bengt Richter

                #8
                Re: Coding Style: Defining Functions within Methods?

                On Sun, 7 Sep 2003 08:11:15 +0000 (UTC), JCM <joshway_withou t_spam@myway.co m> wrote:
                [color=blue]
                >Bengt Richter <bokr@oz.net> wrote:[color=green]
                >> I like defining nested functions except for the fact that a definition is executable code
                >> in itself, and will be re-executed each time the outer function or method is called. I'm
                >> not sure how long MAKE_FUNCTION or MAKE_CLOSURE take to execute, but IWT it must mean allocating
                >> and glueing together the dynamic elements necessary for a distinct function/closure instance,
                >> and then disposing of them at some point on/after their going out of scope, vs. e.g. just locating
                >> a sibling method.[/color]
                >
                >This doesn't need to be slow--it's up to the implementation to try
                >to be as smart as possible. A compiler can do lambda-lifting to
                >transform a program with nested functions to one without, so there
                >really is nothing inherently slow about nested functions.[/color]
                Agreed, but python is very dynamic, so "as smart as possible" may cost
                more overall than calculatedly "dumb" in many cases. As it stands, the way
                you code it will be pretty much the way it happens, so there will be some cost
                to nesting functions. I just don't know how much without timing it. ... resisting ...
                temptation ...

                Succeeded, for now ;-)

                Regards,
                Bengt Richter

                Comment

                Working...