About the use of **args

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Zunbeltz Izaola

    About the use of **args


    Hi

    I'm starting a new proyect and i'm in doubt about diferent interfaces
    for my clases. My clases will have a lot of attributes and i'm want to
    know what aproach could be the best

    1) Define one SetAttribute/GetAttribute pair of method for each
    attribute.
    2) Define one SetAttribute/GetAttribute which argument is a key=value
    format.

    Any advaice?

    Thanks in advance

    Zunbeltz Izaola

    --
    Remove XXX from email: zunbeltz@wm.lc. ehu.esXXX
  • Graham Ashton

    #2
    Re: About the use of **args

    On Wed, 10 Dec 2003 09:38:55 +0100, Zunbeltz Izaola wrote:
    [color=blue]
    > I'm starting a new proyect and i'm in doubt about diferent interfaces
    > for my clases. My clases will have a lot of attributes and i'm want to
    > know what aproach could be the best
    >
    > 1) Define one SetAttribute/GetAttribute pair of method for each
    > attribute.
    > 2) Define one SetAttribute/GetAttribute which argument is a key=value
    > format.[/color]

    I asked a similar question myself when I started out with Python, and I
    got some very good answers that served me well.



    My preferred technique is to just set attributes directly on the object,
    like this:

    shoe = Shoe()
    shoe.laced_up = True
    shoe.is_on_foot = True
    shoe.resoled = False

    You may think that it's a bit nasty because it breaks encapsulation, etc.,
    but Python is designed to let you do stuff quickly and cleanly. You're
    not always in a situation where you need to enforce access so
    strictly. Using attributes directly is more of a Python idiom (see the
    last two posts in the thread I posted earlier).

    Since that earlier thread Python has been given a nice way of
    customising attribute access; properties. Basically, they let you
    define get/set methods that get run when you access/assign to an
    attribute. You benefit by getting a cleaner interface to your class, and
    you only have to define get/set methods when you actually need them (i.e.
    when they have side effects other than getting/setting the attribute).

    For example:

    class Shoe:

    def __init__(self):
    self._laced_up = False
    self.is_on_foot = False
    self.resoled = False

    def _set_laced_up(s elf, boolean):
    self._laced_up = boolean
    if boolean:
    self.is_on_foot = True

    def _get_laced_up(s elf):
    return self._laced_up

    laced_up = property(_get_l aced_up, _set_laced_up)

    I've not run that so it may have syntax errors. It should illustrate the
    principle though; you can use attributes directly until you want to take
    actions when you set them. Then you can make the attribute "private" and
    replace it with a property that access the real attribute, and does
    whatever else you want to do when it's accessed.

    Hope that makes sense.

    -- Graham

    Comment

    • John Roth

      #3
      Re: About the use of **args


      "Zunbeltz Izaola" <zunbeltz@wm.lc .ehu.es.XXX> wrote in message
      news:m1oeuhqd7k .fsf@lcpxdf.wm. lc.ehu.es...[color=blue]
      >
      > Hi
      >
      > I'm starting a new proyect and i'm in doubt about diferent interfaces
      > for my clases. My clases will have a lot of attributes and i'm want to
      > know what aproach could be the best
      >
      > 1) Define one SetAttribute/GetAttribute pair of method for each
      > attribute.
      > 2) Define one SetAttribute/GetAttribute which argument is a key=value
      > format.
      >
      > Any advaice?
      >
      > Thanks in advance
      >
      > Zunbeltz Izaola[/color]

      I presume you're talking about constructing the object,
      not about state changes after it's been constructed and
      released into the wild?

      In that case, the "best" pattern is to never let the object
      appear half constructed. There are a wide variety of ways
      of doing this, from passing all the needed parameters into
      the constructor, to numerous variations on the factory
      pattern. And I wouldn't be adverse to the other responder's
      practice of simply plugging values into the instance while
      it's still in the factory: most real world objects don't contain
      the logic for their construction, so why should our programming
      objects?

      John Roth[color=blue]
      >[/color]


      Comment

      • Mark McEahern

        #4
        Re: About the use of **args

        On Wed, 2003-12-10 at 03:24, Graham Ashton wrote:[color=blue]
        > [snip][/color]
        [color=blue]
        > I've not run that so it may have syntax errors. It should illustrate the
        > principle though; you can use attributes directly until you want to take
        > actions when you set them. Then you can make the attribute "private" and
        > replace it with a property that access the real attribute, and does
        > whatever else you want to do when it's accessed.[/color]

        A couple of points on Graham's example:

        1. You have to subclass from object in order to use property.

        2. When Graham nominalizes private, he means that you can still access
        the attribute variable directly--and that's by design.

        See example below.

        Cheers,

        // m

        #!/usr/bin/env python

        class Shoe:

        def __init__(self):
        self._size = None
        def getSize(self):
        print "In getSize..."
        return self._size
        def setSize(self, size):
        print "In setSize..."
        self._size = size
        size = property(getSiz e, setSize)

        class Shoe2(object):

        def __init__(self):
        self._size = None
        def getSize(self):
        print "In getSize..."
        return self._size
        def setSize(self, size):
        print "In setSize..."
        self._size = size
        size = property(getSiz e, setSize)

        s = Shoe()
        # Since we haven't subclassed from object, the property descriptor
        # doesn't work; notice that setSize() isn't getting called...
        s.size = 1
        print s.size
        # We can still access the "private" member variable. In Python,
        # private is merely a convention.
        print s._size

        # Now that we've subclassed from object, our get/set methods are
        # called.
        s2 = Shoe2()
        s2.size = 1
        print s2.size
        # And we can still access the "private" member variable.
        print s2._size




        Comment

        • Mark McEahern

          #5
          Re: About the use of **args

          On Wed, 2003-12-10 at 03:24, Graham Ashton wrote:[color=blue]
          > [snip][/color]
          [color=blue]
          > I've not run that so it may have syntax errors. It should illustrate the
          > principle though; you can use attributes directly until you want to take
          > actions when you set them. Then you can make the attribute "private" and
          > replace it with a property that access the real attribute, and does
          > whatever else you want to do when it's accessed.[/color]

          A couple of points on Graham's example:

          1. You have to subclass from object in order to use property.

          2. When Graham nominalizes private, he means that you can still access
          the attribute variable directly--and that's by design.

          See example below.

          Cheers,

          // m

          #!/usr/bin/env python

          class Shoe:

          def __init__(self):
          self._size = None
          def getSize(self):
          print "In getSize..."
          return self._size
          def setSize(self, size):
          print "In setSize..."
          self._size = size
          size = property(getSiz e, setSize)

          class Shoe2(object):

          def __init__(self):
          self._size = None
          def getSize(self):
          print "In getSize..."
          return self._size
          def setSize(self, size):
          print "In setSize..."
          self._size = size
          size = property(getSiz e, setSize)

          s = Shoe()
          # Since we haven't subclassed from object, the property descriptor
          # doesn't work; notice that setSize() isn't getting called...
          s.size = 1
          print s.size
          # We can still access the "private" member variable. In Python,
          # private is merely a convention.
          print s._size

          # Now that we've subclassed from object, our get/set methods are
          # called.
          s2 = Shoe2()
          s2.size = 1
          print s2.size
          # And we can still access the "private" member variable.
          print s2._size




          Comment

          • Duncan Booth

            #6
            Re: About the use of **args

            Mark McEahern <marklists@mcea hern.com> wrote in
            news:mailman.27 .1071059861.930 7.python-list@python.org :
            [color=blue]
            > # We can still access the "private" member variable. In Python,
            > # private is merely a convention.
            > print s._size[/color]

            Except that in Python the convention for private variables is to begin them
            with two underscore characters, and then it is more than just a convention:
            [color=blue][color=green][color=darkred]
            >>> class Shoe2(object):[/color][/color][/color]

            def __init__(self):
            self.__size = None
            def getSize(self):
            print "In getSize..."
            return self.__size
            def setSize(self, size):
            print "In setSize..."
            self.__size = size
            size = property(getSiz e, setSize)

            [color=blue][color=green][color=darkred]
            >>> s2 = Shoe2()
            >>> s2.size = 1[/color][/color][/color]
            In setSize...[color=blue][color=green][color=darkred]
            >>> print s2.size[/color][/color][/color]
            In getSize...
            1[color=blue][color=green][color=darkred]
            >>> print s2.__size[/color][/color][/color]

            Traceback (most recent call last):
            File "<pyshell#1 1>", line 1, in -toplevel-
            print s2.__size
            AttributeError: 'Shoe2' object has no attribute '__size'

            Of course, it doesn't absolutely prevent you accessing the private variable
            if you know what you are doing, but then neither do C++ or Java:
            [color=blue][color=green][color=darkred]
            >>> print s2._Shoe2__size[/color][/color][/color]
            1


            --
            Duncan Booth duncan@rcp.co.u k
            int month(char *p){return(1248 64/((p[0]+p[1]-p[2]&0x1f)+1)%12 )["\5\x8\3"
            "\6\7\xb\1\x9\x a\2\0\4"];} // Who said my code was obscure?

            Comment

            • Jacek Generowicz

              #7
              Re: About the use of **args

              Zunbeltz Izaola <zunbeltz@wm.lc .ehu.es.XXX> writes:
              [color=blue]
              > Hi
              >
              > I'm starting a new proyect and i'm in doubt about diferent interfaces
              > for my clases. My clases will have a lot of attributes and i'm want to
              > know what aproach could be the best
              >
              > 1) Define one SetAttribute/GetAttribute pair of method for each
              > attribute.
              > 2) Define one SetAttribute/GetAttribute which argument is a key=value
              > format.
              >
              > Any advaice?[/color]

              3) Not have any setters or getters at all.

              Ask yourself: "what is the point of getters and setters?".

              The most common answers are:

              a) Data hiding, privacy, etc.

              b) To protect myself against breaking the interface when I change the
              implementation of my object.

              c) Give you and your users typing exercise.

              In Python there is no enforced data hiding or privacy: you use a
              leading underscore in the identifier name to indicate to your users
              that something is _not_ part of the interface ... so (a) is irrelevant.

              As for (b), Python provides properties, which allow you to replace an
              attribute with a setter and/or a getter method, while maintaining the
              illusion that there is only an attribute. Properties also allow you to
              implement read-only (or write-only! (or delete-only!!)) attributes.

              (I won't comment on (c) :-)

              If you are a fan of Bertrand Meyer, you might also answer

              d) Attribute access and method calls should look the same.

              I'm not aware of a Python mechanism to make that irrelevant.

              Comment

              • Jacek Generowicz

                #8
                Re: About the use of **args

                Duncan Booth <duncan@NOSPAMr cp.co.uk> writes:
                [color=blue]
                > Mark McEahern <marklists@mcea hern.com> wrote in
                > news:mailman.27 .1071059861.930 7.python-list@python.org :
                >[color=green]
                > > # We can still access the "private" member variable. In Python,
                > > # private is merely a convention.
                > > print s._size[/color]
                >
                > Except that in Python the convention for private variables is to begin them
                > with two underscore characters, and then it is more than just a convention:[/color]

                Now, I always believed that "private" in Python is spelt "_", while
                "mangle this name for me because I want to avoid name clashes in
                multiple inheritance scenarios" is spelt "__".

                However, I've heard _so_ many people make the (in my opinion
                incorrect) claim that "private" is spelt "__", that I'm beginning to
                question my sanity.

                Where is the Python spelling of "private" set in stone ?

                I find the suggestion that a mangled name is somehow "more private"
                than one with a single leading underscore, mildly insulting to the
                clients of your code. The implcation is that they can neither work out
                the (very complicated and cryptic[*]) mangling scheme, not use dir().

                If a Python programmer wants to acces a private attribute, he can do
                so, regardless of the number of leading underscores.

                [*] Sarcasm alert. (This alert was brought to you by the International
                Campaign for Promotion of Understanding between Cultures.)

                Comment

                • Duncan Booth

                  #9
                  Re: About the use of **args

                  Jacek Generowicz <jacek.generowi cz@cern.ch> wrote in
                  news:tyfzne0yeq p.fsf@pcepsft00 1.cern.ch:
                  [color=blue][color=green]
                  >> Except that in Python the convention for private variables is to
                  >> begin them with two underscore characters, and then it is more than
                  >> just a convention:[/color]
                  >
                  > Now, I always believed that "private" in Python is spelt "_", while
                  > "mangle this name for me because I want to avoid name clashes in
                  > multiple inheritance scenarios" is spelt "__".
                  >
                  > However, I've heard _so_ many people make the (in my opinion
                  > incorrect) claim that "private" is spelt "__", that I'm beginning to
                  > question my sanity.
                  >
                  > Where is the Python spelling of "private" set in stone ?[/color]

                  Section 5.2.1 of the Python reference manual in the paragraph headed
                  'Private name mangling'.
                  [color=blue]
                  >
                  > I find the suggestion that a mangled name is somehow "more private"
                  > than one with a single leading underscore, mildly insulting to the
                  > clients of your code. The implcation is that they can neither work out
                  > the (very complicated and cryptic[*]) mangling scheme, not use dir().[/color]

                  Not at all, the mangling is clearly documented. Its purpose is most
                  emphatically NOT to prevent access to your clients.
                  [color=blue]
                  >
                  > If a Python programmer wants to acces a private attribute, he can do
                  > so, regardless of the number of leading underscores.[/color]

                  Good points. I suppose it all depends on your definition of 'private'. To
                  me, there are two reasons why someone might want to use 'private'
                  variables. One is to prevent accidental nameclashes when someone subclasses
                  one of your classes, the other is because you don't trust those poxy
                  programmers who are going to use your class, so you want to burn their
                  fingers if they try.

                  The first of these, Python provides. Ok, it doesn't get it quite right (the
                  name mangling should maybe include the module and package as well as the
                  class), but it does a reasonable job of minimising accidental nameclashes.
                  Python does not attempt to address the second of these issues, preferring
                  to believe that all Python programmers are mature & responsible.

                  C++ fails dismally on the first count, it doesn't hide the names so adding
                  a 'private member' to a base class can break the derived classes. It also
                  fails on the second count, since you can easily bypass private if you wish.

                  To my mind, data hiding is a good reason for using private variables, but
                  preventing knowledgeable users from bypassing the privacy is dubious at
                  best. You are of course free to disagree.

                  --
                  Duncan Booth duncan@rcp.co.u k
                  int month(char *p){return(1248 64/((p[0]+p[1]-p[2]&0x1f)+1)%12 )["\5\x8\3"
                  "\6\7\xb\1\x9\x a\2\0\4"];} // Who said my code was obscure?

                  Comment

                  • Peter Hansen

                    #10
                    Re: About the use of **args

                    Jacek Generowicz wrote:[color=blue]
                    >
                    > Duncan Booth <duncan@NOSPAMr cp.co.uk> writes:
                    >[color=green]
                    > > Mark McEahern <marklists@mcea hern.com> wrote in
                    > > news:mailman.27 .1071059861.930 7.python-list@python.org :
                    > >[color=darkred]
                    > > > # We can still access the "private" member variable. In Python,
                    > > > # private is merely a convention.
                    > > > print s._size[/color]
                    > >
                    > > Except that in Python the convention for private variables is to begin them
                    > > with two underscore characters, and then it is more than just a convention:[/color]
                    >
                    > Now, I always believed that "private" in Python is spelt "_", while
                    > "mangle this name for me because I want to avoid name clashes in
                    > multiple inheritance scenarios" is spelt "__".
                    >
                    > However, I've heard _so_ many people make the (in my opinion
                    > incorrect) claim that "private" is spelt "__", that I'm beginning to
                    > question my sanity.[/color]

                    Distinguish "private" and "protected" , as in C++ and perhaps wider usage.

                    "private" is spelled __ in Python and is supported in a limited fashion
                    by the language, while *protected* is spelled _ and is by convention.

                    -Peter

                    Comment

                    • Fredrik Lundh

                      #11
                      Re: About the use of **args

                      Jacek Generowicz wrote:
                      [color=blue]
                      > I find the suggestion that a mangled name is somehow "more private"
                      > than one with a single leading underscore, mildly insulting to the
                      > clients of your code. The implcation is that they can neither work out
                      > the (very complicated and cryptic[*]) mangling scheme, not use dir().[/color]

                      no, the implication is that they can use their own __variables without
                      having to think about what you're calling your private parts.

                      in contrast, a _variable is not hidden at all.

                      </F>




                      Comment

                      • Zunbeltz Izaola

                        #12
                        Re: About the use of **args

                        "Fredrik Lundh" <fredrik@python ware.com> writes:

                        I want to sum up some ideas in the thread:

                        1) setters and getters are not mandatory.

                        2) The usual way in Python is the direct access
                        [color=blue]
                        > [=] ... b.width # is get
                        > b.width = # is set
                        > del b.width # is del[/color]

                        3) If when setting some attribute there is necesary to have side
                        effects, it can be achive defining __setattr__ and doing the right
                        thing depend on the attribute. (It is possible to raise an
                        exception when the attribute is not in a list/dictionary of usable
                        attributes, to prevent typos and such kind of errors)

                        4) __getattr__ can be defined to deal with undefined attributes. For
                        example it can handle in different way the attributes in a list of
                        permited attributes (see point 3)

                        5) attributes that are computed in the fly, can be get like normal
                        attributes using "property" (property is new in 2.3 or 2.2?)

                        6) attributes and methods that are no part of the user interface are
                        named with and _ in the front. (This is a convention)

                        Are those ideas correct? We can continue with the discussion!!

                        Zunbeltz


                        --
                        Remove XXX from email: zunbeltz@wm.lc. ehu.esXXX

                        Comment

                        • Jacek Generowicz

                          #13
                          Re: About the use of **args

                          Zunbeltz Izaola <zunbeltz@wm.lc .ehu.es.XXX> writes:

                          [snip]
                          [color=blue]
                          > 3) If when setting some attribute there is necesary to have side
                          > effects, it can be achive defining __setattr__ and doing the right
                          > thing depend on the attribute. (It is possible to raise an
                          > exception when the attribute is not in a list/dictionary of usable
                          > attributes, to prevent typos and such kind of errors)
                          >
                          > 4) __getattr__ can be defined to deal with undefined attributes. For
                          > example it can handle in different way the attributes in a list of
                          > permited attributes (see point 3)
                          >
                          > 5) attributes that are computed in the fly, can be get like normal
                          > attributes using "property" (property is new in 2.3 or 2.2?)[/color]

                          [snip]
                          [color=blue]
                          > Are those ideas correct?[/color]

                          Pretty much.

                          Properties are available in 2.2. They only work on new style classes.

                          Just about anything that can be done with properties can be done with
                          __setattr__ &co, but I think that properties are generally preferred,
                          if available.

                          Comment

                          Working...