Why the module does not be defined yet?

class Sample:
    import time
    def __init__(self,arg):
        print(arg)
    def call(self):
        time.sleep(3)
        print('haha')

I had wrote import time in the class.

x = Sample('world')
world
x.call()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in call
NameError: name 'time' is not defined

Why the name ‘time’ is not defined yet?

The module is loaded. It just isn’t in the place where you’re looking for it.

The scoping of class blocks is a little weird in Python. When the interpreter first encounters the block, it runs the code (i.e., the def statements are creating new functions, assignments are assigning, etc.) in a temporary, local scope. However, after it finishes doing that, it gathers up those local variables and uses them to create the class object.

import is a form of assignment in Python, so in your example code, time becomes a local variable (naming the standard library time module, which has now been imported and cached). So when the class is created, it will have a time attribute corresponding to that:

>>> dir(Sample)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'call', 'time']
>>> Sample.time
<module 'time' (built-in)>

But the code in the call method is expecting a global variable instead. At this point, time is not a global variable. Sample is, and it has that attribute; so we could access it like Sample.time.sleep(3).

However, it would be better to just put imports at the top of the file, as is the normal practice. Deferred imports are a special purpose tool.

class Sample:
   import time
   def __init__(self,arg):
       print(arg)
   def call(self):
       time.sleep(3)
       print('haha')

I had wrote import time in the class.

… and that defined the name time only inside the namespace used to
construct the class. You’ll find that Sample.time is a known name.

x = Sample('world')
world
x.call()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "<stdin>", line 6, in call
NameError: name 'time' is not defined

Why the name ‘time’ is not defined yet?

Oh, it got defined. But not where you expected it. The import
statement is just a slightly special assignment statement. It loads a
module (if it isn’t already loaded) and binds it to the import name,
here time. In the namespace where you did the import.

When you look up a name like time (or x) Python looks in the current
namespace (normally the local variables of the function you’re running)
and then in whatever outer namespaces are in use (these exist kind of in
a stack). Normally the outer namespaces for your method will be:

  • the globals (the module namespace, where things like Sample were
    defined)
  • the builtins module where most predefined functions with global
    names as defined, like print or sorted

Where was time defined? In the Sample class. Not in the
global/module namespace.

So your function can’t find it as just time, because such a name is
looked up in:

  • the function local variables
  • the global/module namespace
  • the builtins

You can get at it as self.time, because that looks for .time as:

  • a direct attribute of self
  • in self’s class (or one of its superclasses, eg in object)

But normally we almost never do an import in the top level of a class.
If you really don’t want it in the module namespace (and sometimes we
don’t) you can just import it in the function:

 def call(self):
     import time
     time.sleep(3)
     print('haha')

or alternatively:

 def call(self):
     from time import sleep
     sleep(3)
     print('haha')

which is just as good, and entirely a personal style choice.

Cheers,
Cameron Simpson cs@cskk.id.au