[Tutor] Importing from classes or functions

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Thu Oct 30 20:46:39 EST 2003


> > Think of 'import math' as a statement that creates a local variable
> > called 'math'.  Then the error message should be less mysterious:
> >
> > > >>> class sinnum(int):
> > > ...     def __init__(s, number):
> > > ...         import math
> > > ...         s.num = number
> > > ...     def sin(s):
> > > ...         return math.sin(s)
> > > ...
> > > >>> x = sinnum(5)
> > > >>> x.sin()
> > > Traceback (most recent call last):
> > >   File "<input>", line 1, in ?
> > >   File "<input>", line 6, in sin
> > > NameError: global name 'math' is not defined
> >
> >
> > 'math' here is a local variable within __init__, so it won't be
> > visible from the 'sin()' function.  So the error is actually not too
> > serious: it's a scope issue.
>
> No, when I tried importing math outside of the __init__ function, it
> didn't do anything.


Hi Daniel,


Let's go back for a moment.  The situation is simliar to something like
this:

###
class TestScope1:
    def __init__(self):
        x = 42

    def test(self):
        print x
###

This breaks with a familiar "NameError" exception because, in test(),
Python has no idea what 'x' means.  So the reason TestScope1 breaks is the
same reason that:

###
class sinnum(int):
    def __init__(s, number):
        import math
        s.num = number
    def sin(s):
        return math.sin(s)
###

breaks.



If we actually wanted to squirrel the value as part of the state of that
TestScope1 instance, we can say something like:

###
class TestScope1_fixed:
    def __init__(self):
        self.x = 42

    def test(self):
        print self.x
###

and we can fix sinnum() by using a similar approach.


> Someone else on the list suggested using the __import__ function (not
> definition, just using the function), and it worked.

True.  But there's nothing special about __import__().  Compare the
__import__() example with:

###
class sinnum(int):
    def __init__(self, number):
        self.num = number
        import math
        self.math = math

    def sin(self):
        return self.math.sin(self)
###

Does that make sense?  Please feel free to ask questions about this, as
variable name scope is a useful concept.




I'm actively trying to ignore the first part of your question:

> > >>> class sinnum(int):
> > ...     def __getattr__(self, attr):
> > ...         def f(*args):
> > ...             return apply(getattr(__builtins__,
> > attr),
> > ...                          (self,) + args)
> > ...         return f
> > ###
> >
> Would you mind explaining that code? I can't understand it, and it
> doesn't seem to work if you're using namespaces. I'd like it to work so
> that the math module is imported locally and math functions can be used
> without namespaces.


because I haven't figured out how to explain it well yet.  *grin*


Talk to you later!




More information about the Tutor mailing list