encapsulation checking features

Alex Martelli aleax at aleax.it
Wed Apr 16 12:24:13 CEST 2003


Eric Scharff wrote:

> Thanks for the reference to PyChecker, I'll have to check it out.
> 
> I've not read enough python code to know how people traditionally treat
> "instance variables that ought to be public" and "instance variables that
> ought to be private" (other than prepending underscores, which I never
> liked).

Whether you like it or not, it *IS* exactly the Pythonic approach --
if you don't prepend an underscore to the name, you're conventionally
saying that name IS part of the public interface to the module or
class -- how it's IMPLEMENTED in the future is up to you, but client
code is entitled to rely on the existence of SOME implementation.


>> But I really don't see the problem here.  If you want myVar.x to
>> call an accessor, you make x into a property of myVar's class,
>> period.  Absolutely no need to design trivial do-nothing accessors
>> either -- you can perfectly well have all client code access all
>> instance variables you want, and if and then such "variables"
>> need to be "computed on the fly" or have special effects when
>> set, then you make them into properties, hey presto.
> 
> I come from a Smalltalk background, which implicitly treats all direct
> variable references as private to a class, requiring do-nothing accessors.
> The advantage of these in Smalltalk is that I find it makes refactoring
> easier - you can ask Smalltalk to tell you everywhere where the "myVar:"
> setter is called.  I could grep all of my python code for ".myVar =" but
> that technique is slightly less accurate.

Python is full of features that will make it nearly impossible (not
just "slightly less accurate") to statically identify "all places
where X is performed".  For example, consider identifying "all
places where function F is called" (no matter whether it's a method,
etc).  Grepping for "F(" isn't just "slightly less accurate", it's
simply broken, because it will miss all the occurrences of e.g.
    mylist.append(F)
in some place in the code with some other places then having e.g
    mylist[chooser()]()

If your main purpose in life is easily and statically finding "all
places where X is performed", then Python is one of the worst
languages you could possibly choose -- most aspects of its power,
such as "everything is first-class", dynamism, etc, etc militate
_against_ allowing easy and accurate static analysis.

Even if one was willing to bear the burden of zillion of silly
empty deuced boilerplate accessors everywhere (which I wouldn't be:
the fact that Python lets me do without boilerplate is one of the
crucial ways it enhances my productivity), Python STILL wouldn't
let you satisfy your heart's desire in this.  E.g. even if you
did use bedraggled setMyVar and getMyVar semantically-redundant
accessors everywhere, STILL in order to easily find all calls to
them you'd have to impose LOTS more limitations and discipline
on client-code -- no sticking such methods in lists and dicts, no
passing boundmethods as callback arguments to other components,
and so on, and so forth.

I don't think that trying to code Smalltalk in Python is a winning
idea, in general -- any more than trying to code Fortran in C, or
any other such combination.  "If you want Smalltalk, you know
where to find it", to paraphrase Ritchie [some claim it's a legend
that Ritchie ever said this, but the concept is surely germane;-)].

If you find that your overall productivity gets _damaged_ by
using Python Pythonically (for example because you so strongly
dislike some of Python's rules and conventions -- such as the
leading-underscore idea -- that you refuse to use them, or spend
your time and energy loathing what you're coding rather than
coding it;-), then it's quite possible that you should instead
try Ruby, or Smalltalk variants (Squeak?), or other languages
yet.  Personally, I think MOST programmers will easily be able
to adapt, but I've seen some counterexamples where somebody was
*SO* utterly attached to idioms and approaches of some other
language (Perl being the one I observed most often) that, no
matter what, they kept "trying to code Perl [or other X] in
Python" and ended up with a net loss in terms of productivity
*AND FUN* (I think it's important to have FUN programming --
if you spend your time and energy *fighting* your tools because
you hate the way they work, it's unlikely that you're having
fun, unless, perhaps you have a peculiarly pugnacious
personality...;-).


>>> These are great features to have, but it'd be nice to have warnings to
>>> discourage their use at times.
> 
>> I can see that for the "ensure all instance variables exist at
>> the end of __init__".  I can't see that, given the existence of
>> properties, for "no access to instance attributes from outside
>> of methods".  Perhaps you can clarify what advantage the latter
>> would provide, that properties just can't...?
> 
> Here's an example:  I implemented a simulation of something using python
> objects that represent objects in the simulation.  In my rapid
> prototyping,
> the objects had two "aspects", the simulation and the visualization. 
> Every object had a tkItem instance variable that the object used to
> configure
> using Tkinter.  Now, I want to create an easy way to enable and disable
> the
> views, or have more flexible views.  Turning off the visualization means
> finding all the references to tkItems and changing their structure.
> 
> Yes, it was badly written to start, but it made sense at the time. :)  Now
> I want to get as much built-in help for refactoring as possible.

I'm not sure I entirely follow -- you're talking about restructuring
the CLIENT code of your simulation?  Where said client code is entirely
under your control?  You just can't do it by static analysis, not
reliably for all usage patterns that client-code may have used -- but
if the client code is entirely under your control, why wouldn't just
grepping for the attributename you need to refactor around be entirely
satisfactory?  If you've used peculiar ways of access, such as
getattr with runtime-computer string expressions, you'll need a bit
more work, of course, but how do you think any static analysis tool
might help you with those...?


Alex





More information about the Python-list mailing list