How to get/set class attributes in Python

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Kalle Anke

    How to get/set class attributes in Python

    I'm coming to Python from other programming languages. I like to
    hide all attributes of a class and to only provide access to them
    via methods. Some of these languages allows me to write something
    similar to this

    int age( )
    {
    return theAge
    }

    void age( x : int )
    {
    theAge = x
    }

    (I usually do more than this in the methods). I would like to do
    something similar in Python, and I've come up with two ways to do
    it: The first one uses the ability to use a variable number of
    arguments ... not very nice. The other is better and uses
    __setattr__ and __getattr__ in this way:

    class SuperClass:
    def __setattr__( self, attrname, value ):
    if attrname == 'somevalue':
    self.__dict__['something'] = value
    else:
    raise AttributeError, attrname

    def __str__( self ):
    return str(self.someth ing)

    class Child( SuperClass ):
    def __setattr__( self, attrname, value ):
    if attrname == 'funky':
    self.__dict__['fun'] = value
    else:
    SuperClass.__se tattr__( self, attrname, value )

    def __str__( self ):
    return SuperClass.__st r__( self ) + ', ' + str(self.fun)

    Is this the "Pythonic" way of doing it or should I do it in a different
    way or do I have to use setX/getX (shudder)




  • Steve Jorgensen

    #2
    Re: How to get/set class attributes in Python

    On Sun, 12 Jun 2005 11:54:52 +0200, Kalle Anke <skromta@gmail. com> wrote:
    [color=blue]
    >I'm coming to Python from other programming languages. I like to
    >hide all attributes of a class and to only provide access to them
    >via methods. Some of these languages allows me to write something
    >similar to this
    >
    >int age( )
    >{
    > return theAge
    >}
    >
    >void age( x : int )
    >{
    > theAge = x
    >}
    >
    >(I usually do more than this in the methods). I would like to do
    >something similar in Python, and I've come up with two ways to do
    >it: The first one uses the ability to use a variable number of
    >arguments ... not very nice. The other is better and uses
    >__setattr__ and __getattr__ in this way:
    >
    >class SuperClass:
    > def __setattr__( self, attrname, value ):
    > if attrname == 'somevalue':
    > self.__dict__['something'] = value
    > else:
    > raise AttributeError, attrname
    >
    > def __str__( self ):
    > return str(self.someth ing)
    >
    >class Child( SuperClass ):
    > def __setattr__( self, attrname, value ):
    > if attrname == 'funky':
    > self.__dict__['fun'] = value
    > else:
    > SuperClass.__se tattr__( self, attrname, value )
    >
    > def __str__( self ):
    > return SuperClass.__st r__( self ) + ', ' + str(self.fun)
    >
    >Is this the "Pythonic" way of doing it or should I do it in a different
    >way or do I have to use setX/getX (shudder)[/color]

    I'm totally new to Python myself, but my understanding is that

    Comment

    • tiissa

      #3
      Re: How to get/set class attributes in Python

      Kalle Anke wrote:[color=blue]
      > I'm coming to Python from other programming languages. I like to
      > hide all attributes of a class and to only provide access to them
      > via methods. Some of these languages allows me to write something
      > similar to this
      >
      > int age( )
      > {
      > return theAge
      > }
      >
      > void age( x : int )
      > {
      > theAge = x
      > }
      >
      > (I usually do more than this in the methods).[/color]

      You can 'hide' you getsetters using a property attribute[1]:
      [color=blue][color=green][color=darkred]
      >>> class person(object):[/color][/color][/color]
      ... def __init__(self):
      ... self.age = 0
      ... def set_age(self, age):
      ... print 'set %d' % age
      ... self.__age = age
      ... def get_age(self):
      ... print 'get'
      ... return self.__age
      ... age = property(get_ag e, set_age)
      ...[color=blue][color=green][color=darkred]
      >>> joe = person()[/color][/color][/color]
      set 0[color=blue][color=green][color=darkred]
      >>> joe.age = 20[/color][/color][/color]
      set 20[color=blue][color=green][color=darkred]
      >>> print joe.age[/color][/color][/color]
      get
      20[color=blue][color=green][color=darkred]
      >>>[/color][/color][/color]

      [1]http://docs.python.org/lib/built-in-funcs.html

      Comment

      • Steve Jorgensen

        #4
        Re: How to get/set class attributes in Python

        On Sun, 12 Jun 2005 03:15:27 -0700, Steve Jorgensen <nospam@nospam. nospam>
        wrote:

        ....[color=blue][color=green]
        >>Is this the "Pythonic" way of doing it or should I do it in a different
        >>way or do I have to use setX/getX (shudder)[/color]
        >
        >I'm totally new to Python myself, but my understanding is that[/color]
        ....

        Oops - I thought I cancelled that post when I relized I was saying nothing,
        but somehow, it got posted.

        Comment

        • alex23

          #5
          Re: How to get/set class attributes in Python

          Kalle Anke wrote:[color=blue]
          > I'm coming to Python from other programming languages. I like to
          > hide all attributes of a class and to only provide access to them
          > via methods.[/color]

          I'm pretty fond of this format for setting up class properties:

          class Klass(object):
          def propname():
          def fget: pass
          def fset: pass
          def fdel: pass
          def doc: """pass"""
          return locals()
          propname = property(**prop name())

          (Replacing 'pass' in the getters & setters et.al with the actual
          functionality you want, of course...)

          This method minimises the leftover bindings, effectively leaving the
          getter/setter methods bound only to the property, ensuring they're only
          called when the property is acted upon.

          Incidentally, kudos & thanks to whomever I originally stole it from :)

          -alex23

          Comment

          • deelan

            #6
            Re: How to get/set class attributes in Python

            Kalle Anke wrote:[color=blue]
            > I'm coming to Python from other programming languages. I like to
            > hide all attributes of a class and to only provide access to them
            > via methods.[/color]
            (...)[color=blue]
            > Is this the "Pythonic" way of doing it or should I do it in a different
            > way or do I have to use setX/getX (shudder)[/color]

            the pythonic way is to use "property" (as others have already explained)
            only when is *stricly necessary*. this may clarify things up:

            "Python Is Not Java"
            <http://dirtsimple.org/2004/12/python-is-not-java.html>

            HTH.

            --
            deelan <http://www.deelan.com>

            Comment

            • Kalle Anke

              #7
              Re: How to get/set class attributes in Python

              On Sun, 12 Jun 2005 12:20:29 +0200, tiissa wrote
              (in article <42ac0c6d$0$101 02$626a14ce@new s.free.fr>):

              [color=blue]
              > You can 'hide' you getsetters using a property attribute[1]:
              >
              > [1]http://docs.python.org/lib/built-in-funcs.html[/color]

              Thanks, this is exactly what I was looking for


              Comment

              • John Machin

                #8
                Re: How to get/set class attributes in Python

                Kalle Anke wrote:[color=blue]
                > On Sun, 12 Jun 2005 12:20:29 +0200, tiissa wrote
                > (in article <42ac0c6d$0$101 02$626a14ce@new s.free.fr>):
                >
                >
                >[color=green]
                >>You can 'hide' you getsetters using a property attribute[1]:
                >>
                >>[1]http://docs.python.org/lib/built-in-funcs.html[/color]
                >
                >
                > Thanks, this is exactly what I was looking for
                >
                >[/color]

                OTOH, I beseech you to consider an attitude transplant :-)

                I.e. put your effort into writing code that allows people to do useful
                things, rather than opaque guff full of __blahblah__ that stops them
                from doing dopey or evil things they're usually smart enough or
                righteous enough not to do anyway.

                BTW, what do you think of this:

                sys.maxint = -12345

                Cheers & HTH,
                John

                Comment

                • Kalle Anke

                  #9
                  Re: How to get/set class attributes in Python

                  On Sun, 12 Jun 2005 13:59:27 +0200, deelan wrote
                  (in article <jrVqe.16350$TR 5.11328@news.ed isontel.com>):
                  [color=blue]
                  > the pythonic way is to use "property" (as others have already explained)
                  > only when is *stricly necessary*. this may clarify things up:[/color]

                  Thanks for the link (although Java was only one of the languages I was
                  thinking of).

                  Anyway, I got another "problem" (read: being used to do it like this in other
                  languages). I'm used to use statically typed languages and for me one of the
                  advantages is that I can be sure that a parameter is of a certain type. So in
                  Java I could write

                  void doSomething( data : SomeClass ){ ... }

                  and I would be sure at compile time that I would only get SomeClass objects
                  as parameters into the method.

                  In learning Python I've understood that I should write code in such a way
                  that it can handle different data and this is fine with me. But what if I
                  have a class where different attributes should only have values of a certain
                  type and everything else is an error.

                  For example, if I have an class that defines three attributes: first and last
                  name plus email address. The only valid data types for the first two are
                  strings and for the last an EmailAddress class.

                  How should I handle this in Python?

                  Should I use just don't care (but I'm going to send the data to a database so
                  I need to ensure that the data is OK)? Should I use 'isinstance' and check
                  manually? Or should I do something else?

                  (I've been trying to figure out this and other things but I haven't found
                  much in books or web sites)

                  jem


                  Comment

                  • Kalle Anke

                    #10
                    Re: How to get/set class attributes in Python

                    On Sun, 12 Jun 2005 15:35:15 +0200, John Machin wrote
                    (in article <42AC3A13.90205 03@lexicon.net> ):
                    [color=blue]
                    > OTOH, I beseech you to consider an attitude transplant :-)[/color]

                    ;-)
                    [color=blue]
                    > I.e. put your effort into writing code that allows people to do useful
                    > things, rather than opaque guff full of __blahblah__ that stops them
                    > from doing dopey or evil things they're usually smart enough or
                    > righteous enough not to do anyway.[/color]

                    I'm just trying to protect myself from myself :-) No, I'm playing around with
                    different ways of doing things, trying to learn Python and how do things in a
                    proper "pythonic" way.

                    In this case I'm going to have a class with some properties that are going to
                    be stored in a database, I don't want to read all the properties everytime I
                    recreate the object from the database but I still want to give the impression
                    that the attributes exists and is available. So my idea was to "hide" the
                    actual database stuff ...
                    [color=blue]
                    > BTW, what do you think of this:
                    >
                    > sys.maxint = -12345[/color]

                    I don't really understand what you're meaning.

                    jem


                    Comment

                    • Dan Sommers

                      #11
                      Re: How to get/set class attributes in Python

                      On Sun, 12 Jun 2005 15:35:46 +0200,
                      Kalle Anke <skromta@gmail. com> wrote:
                      [color=blue]
                      > In learning Python I've understood that I should write code in such a
                      > way that it can handle different data and this is fine with me. But
                      > what if I have a class where different attributes should only have
                      > values of a certain type and everything else is an error.[/color]
                      [color=blue]
                      > For example, if I have an class that defines three attributes: first
                      > and last name plus email address. The only valid data types for the
                      > first two are strings and for the last an EmailAddress class.[/color]
                      [color=blue]
                      > How should I handle this in Python?[/color]
                      [color=blue]
                      > Should I use just don't care (but I'm going to send the data to a
                      > database so I need to ensure that the data is OK)? Should I use
                      > 'isinstance' and check manually? Or should I do something else?[/color]

                      One key phrase here is "duck typing": if it walks like a duck, and
                      swims like a duck, and quacks like a duck, then it's a duck, or at least
                      you can assume it's a duck. For example:

                      def put_something( file_open_for_w riting, something ):
                      file_open_for_w riting.write( str( something ) )

                      I don't care if file_open_for_w riting is "really a file," as long it has
                      a "write" method that writes a string somewhere.

                      The other key phrase is "we're all adults here": if I import sin from
                      the math module and pass it a unicode string, I get what I deserve.

                      In lower-level methods/functions, I usually just assume that parameters
                      are correct, and let the higher-level code catch any exceptions that
                      occur becuase it (the higher-level code) messed up and passed the wrong
                      kind of parameter. For example, UI code *has* to check things that
                      users type, but once that happens, there's no need for my program to
                      recheck every parameter on every function call all the way down. Either
                      everything works, or that same UI code catches and logs a TypeError or
                      ValueError or KeyError exception and asks the user what to do next.

                      Regards,
                      Dan

                      --
                      Dan Sommers
                      <http://www.tombstoneze ro.net/dan/>

                      Comment

                      • George Sakkis

                        #12
                        Re: How to get/set class attributes in Python

                        "alex23" wrote:
                        [color=blue]
                        > Kalle Anke wrote:[color=green]
                        > > I'm coming to Python from other programming languages. I like to
                        > > hide all attributes of a class and to only provide access to them
                        > > via methods.[/color]
                        >
                        > I'm pretty fond of this format for setting up class properties:
                        >
                        > class Klass(object):
                        > def propname():
                        > def fget: pass
                        > def fset: pass
                        > def fdel: pass
                        > def doc: """pass"""
                        > return locals()
                        > propname = property(**prop name())
                        >
                        > (Replacing 'pass' in the getters & setters et.al with the actual
                        > functionality you want, of course...)
                        >
                        > This method minimises the leftover bindings, effectively leaving the
                        > getter/setter methods bound only to the property, ensuring they're only
                        > called when the property is acted upon.
                        >
                        > Incidentally, kudos & thanks to whomever I originally stole it from :)
                        >
                        > -alex23[/color]

                        And a slight improvement in readability IMHO (for python 2.4+) is the
                        following recipe:
                        http://aspn.activestate.com/ASPN/Coo.../Recipe/410698.
                        Using the Property decorator, the property declaration above becomes:

                        class Klass(object):
                        @Property # <--- the capitalized 'P' is not a typo
                        def propname():
                        '''Documentatio n'''
                        def fget: pass
                        def fset: pass
                        def fdel: pass

                        The Property decorator peeks automagically the fget, fset, fdel and
                        __doc__ from the property's locals(), instead of having the property
                        return locals() explicitly. Also, it doesn't break when the property
                        defines local variables other than [fget, fset, fdel, doc].

                        George

                        Comment

                        • Chris Spencer

                          #13
                          Re: How to get/set class attributes in Python

                          Kalle Anke wrote:[color=blue]
                          > On Sun, 12 Jun 2005 13:59:27 +0200, deelan wrote
                          > (in article <jrVqe.16350$TR 5.11328@news.ed isontel.com>):
                          >
                          > void doSomething( data : SomeClass ){ ... }
                          >
                          > and I would be sure at compile time that I would only get SomeClass objects
                          > as parameters into the method.[/color]

                          Being an untyped language, Python does not require you to enforce types.
                          However, for those that require such functionality, you can get away
                          with using the "assert" statement. For example, if I wanted to make sure
                          my function foo was only given instances of class Bar, I'd write
                          something like:
                          [color=blue][color=green][color=darkred]
                          >>> class Bar: pass
                          >>> def foo(bar):[/color][/color][/color]
                          .... assert isinstance(bar, Bar), "argument is not of type Bar"
                          .... print "argument must be of type Bar"
                          ....[color=blue][color=green][color=darkred]
                          >>> bar = Bar()
                          >>> foo(bar)[/color][/color][/color]
                          argument must be of type Bar[color=blue][color=green][color=darkred]
                          >>> foo(123)[/color][/color][/color]
                          Traceback (most recent call last):
                          File "<stdin>", line 1, in ?
                          File "<stdin>", line 2, in foo
                          AssertionError: argument is not of type Bar[color=blue][color=green][color=darkred]
                          >>>[/color][/color][/color]

                          Chris

                          Comment

                          • Steven D'Aprano

                            #14
                            Re: How to get/set class attributes in Python

                            On Sun, 12 Jun 2005 14:40:26 +0000, Chris Spencer wrote:
                            [color=blue]
                            > Being an untyped language, Python does not require you to enforce types.
                            > However, for those that require such functionality, you can get away
                            > with using the "assert" statement.[/color]

                            Assuming that Python isn't executed with the optimize switch, which
                            disables assert.

                            $ python -O
                            Python 2.3.3 (#1, May 7 2004, 10:31:40)
                            [GCC 3.3.3 20040412 (Red Hat Linux 3.3.3-7)] on linux2
                            Type "help", "copyright" , "credits" or "license" for more information.
                            py>
                            py>
                            py> def tester(x):
                            .... assert type(x) == type(0)
                            .... print "%s is an integer." % x
                            ....
                            py> tester(3)
                            '3 is an integer'
                            py> tester("hello")
                            'hello is an integer'


                            Comment

                            • Peter Dembinski

                              #15
                              Re: How to get/set class attributes in Python

                              Kalle Anke <skromta@gmail. com> writes:

                              [snap]
                              [color=blue][color=green]
                              >> sys.maxint = -12345[/color]
                              >
                              > I don't really understand what you're meaning.[/color]

                              He meant None = 1 :>

                              Comment

                              Working...