Re: Lambda binding solved?

Steven D. Majewski (sdm7g@elvis.med.virginia.edu)
Tue, 1 Mar 1994 12:37:36 -0500

On Mar 1, 1:00, Tim Peters wrote:
>
> I've grown to appreciate the 3-namespace rule (which, as Guido could tell
> you, I squirmed over at first) precisely because I hate being "not sure".
> When there are only 3 places to look (& "builtin" is no burden on the
> brain, so it's more like 2 places), there are only 2 (& more like 1!)
> ways to screw up. That simplicity is worth something, but doesn't seem
> to be valued in this thread.
>

Part of what I was trying to say was that, yes - that simplicity is
worth something, and it certainly works in the most typical cases (
'lambda' being the most glaring counter-example ), so maybe there is
ANOTHER solution than supporting nested arbitrarily namespaces as the
GENERAL case.

[ And maybe that other route is pointed to by the fact that I couldn't
create a new function with different bindings in my kludge/fix, but
had to modify an existing functions attributes. And that you can't
create a module without importing a file. Maybe a solution is to
leave the default symbol search as is, but allow an easy way of
creating and specifying namespaces. ]

Also: I think CSNS could be disastrous combined with Python's
"create it if it ain't there" assignment and lack of declarations!

>
> > I was just recently trying to code something that needed to resolve the
> > default value of a symbol with precedence:
> >
> > instance-variable
> > class-variable
> > module-variable ( i.e. python global )
> > __main__ module-variable ( Really global )
> > [ and if STILL not found, use a "hardwired" default value. ]
>
> Doesn't having five distinct defaults suggest a flaw in the human factors
> of the design this scheme supports <wink>?
>

How many namespaces are in your $PATH or $PYTHONPATH shell variable ?

Yes, it's unusual to want the value of a symbol and have no idea WHERE
exactly to look for it, but search paths for default values are just
one of those cases. It may be possible to set a global value ( in
__main__ ), a module wide value ( for everything defined in that
module ), for a classes of a specific type in that module, or for
a particluar instance of that class. And if none of them are set,
then use the default defined in module 'sys' or module 'defaults'.

[ Forth stuff deleted... ]

>
> > I'm just groping about for another solution.
>
> That's cool! At some abstract level (i.e., one that hasn't burned me in
> practice), I also feel a little discomfort that "the rules" for looking
> up plain variable names have nothing in common with the rules for looking
> up instance variable names. However, I suspect that under CSNS, one
> could view each block as "inheriting" the variable names of its closest-
> containing block, in which case the rules are about the same, except that
> in CSNS each block has only one immediate "superclass". So the real
> challenge is to come up with plain-variable scoping rules that are as
> complicated as instance-variable rules in the presence of multiple
> inheritance <0.9 grin>.
>
> all-this-from-one-harmless-"lambda"?!-ly y'rs - tim
>

Note that it my precedence list above, the class variable is not
necessary on the list if the instance variable IS on the list:
getattr( instance, 'thing' ) returns thing if it is bound in either
the class or the instance. ( And, if you think about it, is why
self.method() [ method is in the Classes __dict__ ] and self.ivar
[ ivar was set in self.__init__, and is in the Instances __dict__ ]
both work.

So you may be onto something, Tim!

In any event, here are two utility functions.
The first is absolutely essential if you want to
use a module's __name__ for any non-decorative purpose
( which typically means you want to eval( __name__ ) and
get the module, i.e. "self". Take my word on it:
The naieve way of doing it just doesn't work!

The second function is only if you need those 4 levels of
lookup ( Both Class+Instance are redundant, remember )
mentioned above. It give you explicit control of the
namespace search. I wrote it to make those default
resolutions easier. But can anyone thing of another case
where one might want, for example, to invert the search space
and have global names have precidence over local names ?

- Steve Majewski (804-982-0831) <sdm7g@Virginia.EDU>
- UVA Department of Molecular Physiology and Biological Physics

# <module names>
#
# 'module()' is needed because:
# (1) while importing, the __name__ string of a module is defined,
# but the module itself is not in the importing namespace (yet!).
# So you may need to defer turning __name__ string into a module symbol.
# (2) Where and IF the module symbol itself is located depends on
# HOW it was imported. You can't depend on resolving __main__.module:
# it may have been imported "from module import *"
# Getting the module from the sys.modules dict appears to get around both
# of these problems. ( Plus, it avoids cluttering up the namespace. Only
# sys is required to be imported, and it's local to this module. )
#

import sys

def module(name):
return sys.modules[name]

#
# resolve will look for symbol-string in scopes, returning the first
# one found, or None.
# scopes should be Instances, Classes, or Modules
# ( or anything that can return hasattr/getattr )
# Instances appear to also return their classes attributes
# so duplication is not necessary.
# Typically used with above function 'module()'
# defpath = resolve( 'path', class-instance,
# module(__name__), module('__main__'), module('sys'))
#

def resolve( symb, *scopes ):
for env in scopes:
if hasattr( env, symb ): return getattr( env, symb )
return None