[Python-ideas] Mitigating 'self.' Method Pollution

Steven D'Aprano steve at pearwood.info
Sat Jul 11 17:07:56 CEST 2015


On Sat, Jul 11, 2015 at 06:38:34PM +1000, Chris Angelico wrote:
> On Sat, Jul 11, 2015 at 6:33 PM, Ben Finney <ben+python at benfinney.id.au> wrote:
> >> And, for folks who still prefer to prefix all their field references
> >> with 'self.', the proposal in no way prevents them from doing so. It
> >> merely allows the rest of us to be a bit less wordy and more pithy in
> >> our code.
> >
> > Python requires explicit declaration of the namespace for names. That
> > protects me from ambiguities that would otherwise be very common in
> > other people's code. I appreciate that and do not want it threatened.
> 
> Not quite true; Python requires explicit declaration of names when
> they're bound to, 

No it doesn't. It only requires an explicit declaration of names when 
you don't wish to use the default *implicit* rule that any name you bind 
to is a local.

Accessing a local is always implicit. You cannot declare locals at all 
(apart from function parameters). You just bind to a name, and Python 
implicitly treats them as local.

Accessing nonlocals and globals may be implicit or explicit, depending 
on whether you use a global or nonlocal declaration.

Accessing builtins is implicit, unless you import builtins and write 
"builtins.len" (say), which we hardly ever do.

In Python, most variables (or name bindings, if you prefer) are 
implicitly scoped. It is rare that they are explicitly scoped as global, 
and when they are, that's usually a code smell. ("Global variables 
considered harmful.") The same applies to attribute access: we normally 
don't explicitly read from a particular scope. That goes against the 
principle of inheritence. When you look up "self.attr", you don't know 
whether the attribute returned will come from the instance __dict__, the 
class, or a superclass, the scope is implied by the history and type of 
the instance itself.

To say nothing of descriptors like property, or methods. That's about as 
implicit as you can get.

A naive reading of the Zen would suggest that, explicit being better 
than implicit (what, always? under all circumstances?), Python must be a 
pretty crap language, it has got so many implicit semantics...

In contrast, the new rule suggested is *explicit*. You explicitly 
declare that a name belongs to the scope:

    self spam, eggs, cheese

declares that spam, eggs and cheese are members of self. That's good 
enough for nonlocals and globals.

(By the way, I used to prefix all my global variables with "g", to be 
explicit that they were global. That stage in my development as a 
programmer didn't last very long. Fortunately, I was never silly enough 
to prefix all my locals with "l".)

Ben has agreed that it would be harmful to have to explicitly scope each 
and every name access:

    if not builtins.len(nonlocals.x + locals.y):
        raise builtins.ValueError(globals.ERROR_MSG)

I trust that everyone agrees with this point. So it seems that explicit 
is *not* always better than implicit. So why do we behave as if the Zen 
of Python is some source of ultimate truth? The Zen is not supposed to 
be a thought-terminating cliche. As Terry Reedy wrote a few years ago:

  "People sometimes misuse Tim Peter's Zen of Python points. He wrote
  them to stimulate thought, not serve as a substitute for thought, and
  certainly not be a pile of mudballs to be used to chase people away."


When you read a line of code in isolation:

    spam = eggs + cheese

there is no hint, no clue, as to which of these are globals, nonlocals, 
locals, or even builtins. And yet we cope with the ambiguity, and I 
don't hear people claiming that we need to explicitly tag names with 
their scope, as we do with attributes.

So what makes attributes so special that we have to break the rules that 
apply to all other variables?

    No tags needed: builtins, globals, nonlocals, locals.

    Tags needed: attributes.


This isn't a rhetorical question, but this post is long enough, and I 
daresay half my readers have tuned out a few paragraphs ago, so I'll 
take my answer to the question to a new post.

-- 
Steve


More information about the Python-ideas mailing list