[Python-Dev] PEP 8 updates/clarifications

Jim Fulton jim at zope.com
Sun Dec 11 17:20:24 CET 2005


Ian Bicking wrote:
 > I was reading through PEP 8, and I think there's a few things that could
 > be clarified or updated:

Good idea.

...

>      Designing for inheritance
> 
>        Always decide whether a class's methods and instance variables
>        should be public or non-public.  In general, never make data
>        variables public unless you're implementing essentially a
>        record.   It's almost always preferrable to give a functional
 >        interface to your class instead (and some Python 2.2
 >        developments will make this much nicer).
 >
 > Yes, Python 2.2 developments have made this better.  Use of property()
 > should be suggested.

This seems outdated.  My impression, in part from time spent
working with the Python Labs guys, is that it is fine to have public
data sttributes even for non-"record" types.  In fact, I would argue that
any time you would be tempted to provide "getFoo()" and "setFoo(v)"
for some "private attribute _foo", it would be better to make it
public.  I certainly find "blah.foo" and "blah.foo = v" to be much
better than "blah.getFoo()" and blah.setFoo(v)".

Certainly, properties provide a safety belt.  I would argue it this
way: Python APIs can include attributes as well as methods.
Exposure of an attribute need not constrain the implementation, thanks
to properties.  OTOH, I wouldn't bother with a property unless it's needed.


> 
>        Also decide whether your attributes should be private or not.
>        The difference between private and non-public is that the former
>        will never be useful for a derived class, while the latter might
>        be.  Yes, you should design your classes with inheritence in
>        mind!
> 
>        Private attributes should have two leading underscores, no
>        trailing underscores.
> 
> This conflicts with a previous suggestion "Generally, double leading 
> underscores should be used only to avoid name conflicts with attributes 
> in classes designed to be subclassed."  Or perhaps "private attributes" 
> needs to be better explained.

While, on some level, private variables seem attractive, I think that
experience (for everyone I know) has shown them to be an attractive
nuisance.  I recommend discouraging them.

I'll note that, IMO:

- If you have to worry about protecting attributes from subclasses,
   maybe should shouldn't be using inheritence.

   (This may be too bold a statement, but perhaps the first
    rule of inheritence should echo Fowler's first rule of Distribution:
    "don't inherit". :)

    Increasingly, I like to use inheritence only to avoid "boiler plate"
    implementations, such as default methods or data implementations that
    almost all implementations of some API are going to do the same way.

    On rare occasions, I find inheritence to be, sadly, unavoidable.

    I should also make a distinction between what I would call "private"
    and "public" inheritence.  Private inheritence is between classes
    that are part of a single implementation unit or having a single
    implementor.  With private inheritence, there is much less danger
    since the same people are responsible for the base classes
    and subclasses.  It is public inheritence, where separate people
    maintain the base and subclasses where I think inhetitence should
    be used sparingly.

    Public inheritence causes too much coupling.
   )

- If you really have to use "public" inheritence, then consider naming
   conventions. I think ZODB's use of the _p_ variables has worked well
   for variables reserved for the base class attributes. (Although, I
   think if I could do it over, I would use _persistent_ rather than
   _p_.)

I'll also note that, when providing "transpatent" facilities, like
persistence or proxies whos functions are orthogonal to subclass
or proxied-object functionality, I've come to prefer the use of external
functions to access provided functionality.  For example, rather than
using something like: "someproxy._proxy_object" to get a proxied object
from a proxy, I use "getProxiedObject(someproxy)".  This allows the
proxies themselves to remain as transparent as possible.  I intend
to take a similar approach with future versions of ZODB's persistence
framework to avoid _p_ attributes and methods.

>        Non-public attributes should have a single leading underscore,
>        no trailing underscores.
> 
>        Public attributes should have no leading or trailing
>        underscores, unless they conflict with reserved words, in which
>        case, a single trailing underscore is preferrable to a leading
>        one, or a corrupted spelling, e.g. class_ rather than klass.
>        (This last point is a bit controversial; if you prefer klass
>        over class_ then just be consistent. :).
> 
> With class methods, this has become a more important.  Can PEP 8 include 
> a preferred name for the class argument to classmethods?  I personally 
> prefer cls, there are some who use klass, and I haven't see class_ used.

FWIW, as a general rule, I like using a single trailing underscore,
especially for keywords.  It allows the use of meaningful and easy
to remember names.  When the name of a variable should be "class" or
"for" or whatever, it's easy, as a Python programmer, to remember that
I need to add a trailing _.  As a reformed abuser of single-character
variable names, I've come to really hate abbreviations.  It's not only
easier to use unabbreviated names, it's easier to remember them when
reading code. (Note that ease of use hinges on editors that automate
typeing of repeated names.)

Jim

-- 
Jim Fulton           mailto:jim at zope.com       Python Powered!
CTO                  (540) 361-1714            http://www.python.org
Zope Corporation     http://www.zope.com       http://www.zope.org


More information about the Python-Dev mailing list