utility functions within a class?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Salerno

    #16
    Re: utility functions within a class?

    Scott David Daniels wrote:[color=blue]
    > John Salerno wrote:[color=green]
    >> Dennis Lee Bieber wrote:[color=darkred]
    >>> ... Single underscores are a convention/signal to the programmer that
    >>> "this method/attribute" is considered "private" and should only be used
    >>> by other methods within the class that defined it. The language does no
    >>> enforcement of usage....[/color]
    >>
    >> I see. But isn't there something about a single leading underscore
    >> that doesn't import when you use from X import *? Or am I thinking of
    >> something else? Is that also the double underscore?[/color]
    >
    > That has to do with module contents, and is a completely separate issue.
    > If you define a module with a variable name '__all__' which is a list
    > (or tuple) of strings, only module elements with those names will be
    > imported with a "from module import *". If you fail to define the
    > '__all__' element, all names which do not start with an underscore will
    > be imported.
    >
    > --Scott David Daniels
    > scott.daniels@a cm.org[/color]

    Thanks, that's what I was thinking of. So it doesn't apply to the
    contents within a class, just top-level contents?

    Comment

    • Scott David Daniels

      #17
      Re: utility functions within a class?

      John Salerno wrote:[color=blue]
      > Scott David Daniels wrote:[color=green]
      >> John Salerno wrote:[color=darkred]
      >>> ... But isn't there something about a single leading underscore
      >>> that doesn't import when you use from X import *? Or am I thinking of
      >>> something else? Is that also the double underscore?[/color]
      >>
      >> That has to do with module contents, and is a completely separate issue.
      >> If you define a module with a variable name '__all__' which is a list
      >> (or tuple) of strings, only module elements with those names will be
      >> imported with a "from module import *". If you fail to define the
      >> '__all__' element, all names which do not start with an underscore will
      >> be imported.[/color]
      >
      > Thanks, that's what I was thinking of. So it doesn't apply to the
      > contents within a class, just top-level contents?[/color]

      Precisely, a "from ... import *" only creates a bunch of names bound to
      a module's top-level contents (at the time of execution of the
      "from ... import *"), and does not affect anything about those bound
      values (except, of course, the refcount).

      --
      -Scott David Daniels
      scott.daniels@a cm.org

      Comment

      • bruno at modulix

        #18
        Re: utility functions within a class?

        John Salerno wrote:[color=blue]
        > John Salerno wrote:
        >[color=green]
        >> jeffshannon@gma il.com wrote:
        >>[color=darkred]
        >>> Even if you don't end up referring to self or any instance
        >>> attributes within the method[/color]
        >>
        >>
        >> Hmm, follow-up: I *do* plan to refer to instance attributes inside
        >> these methods (self.something ), but does that require that they be
        >> instance methods, or can they still reference 'self' since they are
        >> inside the class?
        >>
        >> They won't be called directly from an instance, which is why I
        >> wondered about making them static or class methods, but can static or
        >> class methods use self, or does it have to be an instance method in
        >> that case?[/color]
        >
        >
        > Ugh, sorry about another post, but let me clarify: In these utility
        > functions, I need to refer to an attribute of an instance,[/color]

        So you want ordinary methods.
        [color=blue]
        > but these
        > functions will be called from another method in the class, not from the
        > instance itself.[/color]

        yes, they will:

        class Parrot(object):
        def _func1(self, whatever):
        print whatever

        def talk(self):
        self._func1('vr oom')
        [color=blue]
        > Is this even possible, or would 'self' have no meaning
        > when used this way?[/color]

        You probably noticed that 'self' (or whatever you name it - but better
        to stick to convention) *must* be defined as the first param of a
        'method'. The reason for it is that what we commonly call 'methods' are
        in fact plain Python functions. It's only when they are looked up on an
        instance that they are wrapped into a 'method' object (read about the
        descriptor protocol to learn how...), that in turn calls the function,
        passing it the instance as first param.

        For saying it short (warning: over-simplification ahead), the usual
        method call idiom:

        myObj.myMethod( arg)

        is syntactic sugar for:

        myObj.__class__ .myMethod(myObj , arg)


        HTH.

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

        Comment

        • bruno at modulix

          #19
          Re: utility functions within a class?

          John Salerno wrote:[color=blue]
          > blair.bethwaite @gmail.com wrote:
          >[color=green]
          >> I'm having trouble deciphering what this bit means - "but these
          >> functions will be called from another method in the class, not from the
          >> instance itself", I don't think it makes sense.[/color]
          >
          >
          > Yeah, I'm starting to see that as I tried to implement it. Here's what I
          > came up with, which works:
          >
          > def generate(self, filename):
          > self.head = self.generate_h ead()
          > self.body = self.generate_b ody()
          >
          > So the two generate_* methods are called from within another class
          > method,[/color]

          here, generate() is *not* a class method, it's an instance method (which
          is the default).
          [color=blue]
          > and it seemed necessary to still call them from an instance.
          > What I originally meant was that they would not be called from an
          > instance *outside* the class itself, i.e. they won't be used when
          > writing another script, they are only used by the class itself.[/color]

          Yeps, that's pretty common in any OO language. In most mainstream OOPLs,
          these methods would have the 'protected' access restriction modifier. In
          Python, we rely on the convention that an attribute whose name is
          prefixed with a single underscore is an implementation detail - not part
          of the API - and should not be called by client code. Just renaming
          these two methods is enough to warn users of your code that they're on
          their own if they start messing with them.

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

          Comment

          • bruno at modulix

            #20
            Re: utility functions within a class?

            blair.bethwaite @gmail.com wrote:[color=blue]
            > John Salerno wrote:
            >[color=green]
            >>What I originally meant was that they would not be called from an
            >>instance *outside* the class itself, i.e. they won't be used when
            >>writing another script, they are only used by the class itself.[/color]
            >
            >
            > Yep, so you want to encapsulate the functionality that those methods
            > provide,
            >
            > which is the whole point of building them in a class in the
            > first place. And you want them to be private to the class so that they
            > do not form part of the classes public/external interface.
            >
            > In python, as discussed earlier :), you can make them semi-private by
            > using the '__method_name'[/color]

            Blair, please, don't give bad advices. The 'double-leading-underscore'
            stuff has some side-effects (name-mangling), and is meant to protect an
            attribute from accidental overloading. The convention for 'protected'
            attributes (which should really be named 'implementation attributes') is
            a *single* leading underscore.


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

            Comment

            • bruno at modulix

              #21
              Re: utility functions within a class?

              John Salerno wrote:[color=blue]
              > John Salerno wrote:
              >[color=green]
              >> blair.bethwaite @gmail.com wrote:
              >>[color=darkred]
              >>> John Salerno wrote:
              >>>
              >>>> What I originally meant was that they would not be called from an
              >>>> instance *outside* the class itself, i.e. they won't be used when
              >>>> writing another script, they are only used by the class itself.
              >>>
              >>>
              >>> Yep, so you want to encapsulate the functionality that those methods
              >>> provide, which is the whole point of building them in a class in the
              >>> first place. And you want them to be private to the class so that they
              >>> do not form part of the classes public/external interface.[/color]
              >>
              >>
              >> But it's right that they should still be regular instance methods? So
              >> from within the class I still call them as self._generate_ head(), etc.?[/color]
              >
              >
              > I tried the underscore method, but I was still able to call it as a
              > regular instance method in the interpreter. Is that what's supposed to
              > happen?[/color]

              Yes. Language-inforced access restriction is totally useless (and is
              quite easy to defeat in C++ and Java FWIW). Python's philosophy is that
              programmers are not braindead monkey-coders that must be protected
              (pardon the pun) from their own stupidity. There's no way to idiot-proof
              a code anyway, so why bother ? The single-underscore prefix means
              'implementation , don't touch or else', and this is quite enough. Most
              python programmers won't touch it - unless they have perfectly valid
              reasons to do so (yes, it happens), and then they will implicitely
              accept the consequences.


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

              Comment

              • John Salerno

                #22
                Re: utility functions within a class?

                bruno at modulix wrote:
                [color=blue]
                > The convention for 'protected'
                > attributes (which should really be named 'implementation attributes')[/color]

                FWIW, I agree. When I hear 'protected attribute' I think of an attribute
                that can only be used within its class and subclasses of it.

                Comment

                • John Salerno

                  #23
                  Re: utility functions within a class?

                  bruno at modulix wrote:
                  [color=blue][color=green]
                  >> but these
                  >> functions will be called from another method in the class, not from the
                  >> instance itself.[/color]
                  >
                  > yes, they will:
                  >
                  > class Parrot(object):
                  > def _func1(self, whatever):
                  > print whatever
                  >
                  > def talk(self):
                  > self._func1('vr oom')
                  > HTH.[/color]

                  yes, all your posts did help...this is exactly what i ended up doing,
                  and i see now why i needed to make them regular methods, despite the
                  fact that they weren't used outside the class (because the instance was
                  still used *inside* the class to call them)

                  Comment

                  Working...