[Python-Dev] PEP 8 updates/clarifications (original) (raw)
Jim Fulton jim at zope.com
Sun Dec 11 17:20:24 CET 2005
- Previous message: [Python-Dev] PEP 8 updates/clarifications
- Next message: [Python-Dev] PEP 8 updates/clarifications
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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
- Previous message: [Python-Dev] PEP 8 updates/clarifications
- Next message: [Python-Dev] PEP 8 updates/clarifications
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]