Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Object-Oriented Python (retired) Inheritance DRY

Lukáš Kriško
Lukáš Kriško
3,155 Points

Import understanding

Hello, I thought that I know what keyword import do but when I try this code below I found out that I don't know what import do. I expect that if I import function(new_word) from module test.py

word = "dog"

def new_word():
    print(word)

into test2.py

from test import new_word

new_word()

it is the same like writing this into test2.py.

def new_word():
    print(word)

new_word()

I try run this code in test2.py and I expected that it will throw an error(word is not defined) because I only import function (not value of word variable) but it runs and writes "dog".Can somebody explain it to me. (I hope that my English was readable.)

3 Answers

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,454 Points

This is an excellent question! Exactly where does the value for word come from?

When you import a function from another module, the global variables from that modules are saved as an attribute of the function. 'word' isn't global on import, but is "seen" as a global when new_word is run:

# Run interactive Python
$ python3
Python 3.4.3 (default, Oct 14 2015, 20:28:29) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
# show 'word' is not define
>>> 'word' in globals()
False
>>> from test1 import new_word
# 'word' still not defined
>>> 'word' in globals()
False
# inspect function
>>> dir(new_word)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
# check function captured globals 
>>> 'word' in new_word.__globals__
True
>>> new_word.__globals__['word']
'dog'
>>> 

# execute in the debugger to see 'word' in captured globals
>>> import pdb
>>> pdb.run('new_word()')
> <string>(1)<module>()->None
(Pdb) 'word' in globals()
False
(Pdb) step
--Call--
> /home/chrisf/devel/Treehouse/questions/lukas-kristo/test1.py(4)new_word()
-> def new_word():
(Pdb) 'word' in globals()
True
(Pdb) step
> /home/chrisf/devel/Treehouse/questions/lukas-kristo/test1.py(5)new_word()
-> print(word)
(Pdb) 'word'
'word'
(Pdb) globals()['word']
'dog'
(Pdb) continue
dog
>>> 
Jason Anders
MOD
Jason Anders
Treehouse Moderator 145,860 Points

Hey there,

I'm not 100% sure, but I believe it is printing "dog" because it is hard coded into the variable word. And in the function you are importing, the function already knows the value of the variable and is printing the passed in variable value, so therefore it will print dog.

:)

Lukáš Kriško
Lukáš Kriško
3,155 Points

I'm not 100% sure but I think that i understand how it works.Thanks. I have just one more question. If I made in one file test.py(for example)this class and i import random library into it.

import random 

class Fight:
    max_damage = 10
    min_damage = 5

    def damage_rand(self):
        damage = random.randint(self.min_damage,self.max_damage)
        return damage

And then I import Fight class into this file(test2.py)

from test import Fight

class Warrior(Fight):
    name="Blabla"

warrior1 = Warrior()

print(warrior1.damage_rand())

When is executed last command (print(warrior1.damage_rand())) it can use randint from random library although I do not import it into test2.py.

Here is my explanation: When I import class Fight from test.py into test2.py class Fight takes functions from random library(because I import random library into test.py) and this functions becomes attributes of this class(or something like that).So when I use this function imported from Fight class

 def damage_rand(self):
        damage = random.randint(self.min_damage,self.max_damage)
        return damage

in test2.py it can use function from random library although random library wasn't imported into test2.py.

Is it correct or wrong explanation?

Chris Freeman
Chris Freeman
Treehouse Moderator 68,454 Points

You are correct. If in test2.py you tried to add new code using randint it would fail without an import:

>>> warrior1.damage_rand()
8
>>> warrior1.damage_rand()
10
>>> random.randint(0, 10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'random' is not defined
>>> import random
>>> random.randint(0, 10)
0
>>> random.randint(0, 10)
6