(newbie) Is there a way to prevent "name redundancy" in OOP ?
pavlovevidence at gmail.com
Wed Jan 10 22:37:38 CET 2007
Martin Miller wrote:
> Carl Banks wrote:
> > Because the usage deceptively suggests that it defines a name in the
> > local namespace. Failing may be too strong a word, but I've come to
> > expect a consistent behavior w.r.t. namespaces, which this violates, so
> > I think it qualifies as a failure.
> I don't see how the usage deceptively suggests this at all. In this
> case -- your sample code for fun() and fun2() -- all were simply
> Pin('aap'). Since no additional namespace argument was supplied,
Exactly. In normal Python, to create a global variable in a local
context, you must specify the namespace. Normally, variables are
always created in the most local context in Python, only. So now you
come in with this this spiffy "look, it creates the variable for you!"
class, but it completely goes against normal Python behavior by
creating the variable in the global namespace even when in a local
context. I think that is deceptive and confusing behvaior for
something that claims to create variables for you.
> > I think programmatically creating variables is fine; I just recommend
> > you not use sys._getframe, nor the automagical namespace self-insertion
> > class, to do it.
> You've explained some of your worries about sys._getframe. It would
> be interesting to hear specifically what it is you don't like about
> the idea of namespace self-insertion -- mainly because of the local
> namespace limitation?
The local namespace thing has nothing to do with it; I would still be
very much against this even if it did work for locals. My main problem
with this is it saddles the class with behavior that interferes with
using it as a normal class. For instance, if you wanted to do
something like this:
p = Pin(pin_name)
At least it looks like it works! But it works only with the
undesriable side-effect of creating a global variable of some unknown
name. It could be no big deal, or it could be a gaping security hole.
(Yes, I know you can just pass in an empty namespace. Thanks for that.
Nice to know it's at least possible to jump though hoops just to
regain normal usage of the class.)
The problem here, see, is the hubris of the author in thinking that he
can anticipate all possble uses of a class (or at least that he can
presume that no user will ever want to use the class in a normal way).
Of course, no author can ever anticipate all possible uses of their
code, and it's inevitable that users will want to use code in a way the
author didn't intend. Most often it's not any hubris on the author's
part, but mere ignorance, and is forgivable.
But when the author deliberately does extra work to cut the user off
from normal usage, then ignorance is no longer a defense: the normal
way was considered, and the author sanctimoniously decided on the
user's behalf that the user would never want or need normal usage of
the class. That is a lot less forgivable.
If you want to respect the user, your class is going to have to change.
1. Reprogram the class so that, BY DEFAULT, it works normally, and only
inserts itself into a namespace when specifically requested. Then, at
least, users can ignore the autoinsertion silliness if they don't want
to use it. Plus, it affords better documentation to readers who don't
know aren't in on the secret of this Pin class (seeing an
"autoinsert=True" passed to the constructor is a clue something's going
2. (Better, IMO) Write a well-named function to do it. E.g.:
if namespace is None:
namespace = sys._getframe(1).f_globals
namespace[name] = Pin(name)
Leave it out of the class. Classes are better off when they only worry
about what's going on in their own namespaces. Leave dealing with
external namespaces to an external function. The function's name
documents the fact that: you're creating a variable, it's global, it's
a Pin. You've gotten surprise down to a small as you're going to get
More information about the Python-list