Best practice for object attributes?

Michael Sparks michaels at rd.bbc.co.uk
Wed Apr 2 17:12:36 CEST 2003


laotseu wrote:

> One outstanding advantage of the second 'idiom' is that it's the right
> way to define *instance* attributes !-) (which is probably what your
> looking for)

Given the first idiom seems to create instance attributes by cloning the
current state of the class attributes, I'm finding it useful is where
certain instance attributes are unlikely to differ much between
instances, or changes infrequently related to object creation. 

For example: if you're creating large numbers of objects which need a
ballpark timestamp, you could timestamp the class periodically, and
reduce your number of calls to gettimeofday.

Another example is in a custom logging class - it has default logging
levels for most objects defined by the class attributes, but can be
raised/lowered on a per instance basis, or globally for all new objects
by changing the class attributes.

> With the first form you get *class* attributes.  Make 2 instances of
> Shrubbery1, change the name of first one to 'Brian', print the name of
> the second one, and then try to understand what is the purpose of the
> 'self' argument in methods.

I'm aware of the meaning of self :) and know that the first form gives
you class attributes. The reason I was asking is because I'd noticed
the following interesting behaviour, which if _intentional_ is useful.

>>> a=shrubbery1()
>>> b=shrubbery1()
>>> a.name,b.name,shrubbery1.name
(None, None, None)                  # a.name, b.name exist - presumed
                                    # references to shrubbery1.name
>>> a.name="hello"
>>> a.name,b.name,shrubbery1.name
('hello', None, None)               # Bzzzt! a.name seems to be
                                    # independent
>>> b.name="brian"
>>> a.name,b.name,shrubbery1.name
('hello', 'brian', None)            # Hmm. So is b.name
>>> shrubbery1.name="Surprise"
>>> a.name,b.name,shrubbery1.name
('hello', 'brian', 'Surprise')      # Changing class leaves existing
                                    # instances unaffected.
>>> a=shrubbery1()                  # Get 2 fresh copies.
>>> b=shrubbery1()
>>> a.name,b.name,shrubbery1.name
('Surprise', 'Surprise', 'Surprise') # a.name, b.name cloned from
                                     # shrubbery1.name

As far as I can tell the behaviour seems to be that you automatically
gain instance attributes that clone the state of the class attributes
at object creation time, which are then independent and can be modified
via the usual self.<attr> syntax later on. (They cannot however be
modified via the self.__dict__[<attr>] syntax since they're not stored
there)

For reference, this behaviour holds with the following python versions:
   * python 2.3 alpha 2
   * python 2.2.1
   * python 2.2.2 stackless

Given it seems consistent across versions, and seems useful (changing
default values for later objects just by updating a class attribute -
eg an external timestamper perhaps) I was wondering if there's a good
reason not to use this.

Thanks,


Michael.
-- 
Michael.Sparks at rd.bbc.co.uk    
British Broadcasting Corporation, Research and Development
Kingswood Warren, Surrey KT20 6NP

This message (and any attachments) may contain personal views
which are not the views of the BBC unless specifically stated.






More information about the Python-list mailing list