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: def fun(pin_name): p = Pin(pin_name) do_something_with(p) 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 on). 2. (Better, IMO) Write a well-named function to do it. E.g.: def create_global_Pin_variable(name,namespace=None): 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 it. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list