Import function difference between EX48 and EX47

in Test file. it is said

from ex48 import lexicon

but in ex 47, it is
from ex47.game import Room

according to what we learnt from ex 47
why cannot we using “from ex48.lexicon import scan”

Welcome @Leslie… It took me a while to understand how imports work in detail.

This is a good explanation of the whole process:

1 Like

You can, but then you’d have scan() right there and it might conflict with another scan() function. Python defines a bunch of built-in functions that cause problems all the time, so it’s best to use a module with yours.

Thank you. It seems that I still cannot find the answer
It seems that it is difference between importing module and class

Thank you Zed. I tried but doesn’t work. Is that the difference between importing module and class?

You need to show some code Leslie. Nobody can help you unless they see code or screenshots.

Hi Zed:
I tried 3 cases in lexicon_text.py while importing lexcicon.py

Case1 : I tried the same way as ex47 as
"
from nose.tools import *
from ex48.lexicon import lexicon
"
It shows the message as below:
ERROR: Failure: ImportError (cannot import name lexicon)

Case 2 try to import scan()
"
from nose.tools import *
from ex48 import scan()
"
it shows :
ERROR: Failure: SyntaxError (invalid syntax (lexicon_tests.py, line 2))

Case 3 try to import scan
If I change to
"
from nose.tools import *
from ex48 import scan
"
it shows as below
ERROR: Failure: ImportError (cannot import name scan)

So say to yourself what are you trying to do:

From location import module

Or

From location and module import Class

Or

From module import Class or Function

Python needs to know the location of the file you want to use, especially if you aren’t in that directory. This is often the case when testing as the test suite needs to find all tests from outside/above the tests folder.

If you are trying to import a Class to use, which is most common (so you can access all its attributes and functions, eg. to create a new instance of the object) then note that Classes are capitalised.

This can get confusing if for example you have a folder, file and Class all names the same, but it’s a fairly common idiom:

from app.app import App

What happens if you capitalise the last ‘Lexicon’ in your first example, assuming there’s is a lexicon Class in that file?

1 Like

Thank you.
below can work
"
from nose.tools import *
from ex48 import lexicon
"

But below does not
"
from nose.tools import *
from ex48.lexicon import lexicon
"
ERROR: Failure: ImportError (cannot import name lexicon)

I put lexicon.py in the folder ex48/lexicon.py

I guess in this case it is “From location import module” as code in lexicon.py is as below.

data = {
‘north’: ‘direction’,
‘south’: ‘direction’,
‘west’: ‘direction’,
‘east’ : ‘direction’,
‘go’ : ‘verb’,
‘kill’: ‘verb’,
‘eat’: ‘verb’,
‘take’: ‘verb’,
‘the’: ‘stop’,
‘in’: ‘stop’,
‘off’: ‘stop’,
‘bear’: ‘noun’,
‘princess’: ‘noun’,
‘bear’: ‘noun’
}

def number_check(number):
try:
int(number)
return True
except ValueError:
return False

def scan(sentence):

result = []
##sentence_lowercase = sentence.lower()
words = sentence.split()

for word in words:
    word_type = data.get(word)
    ##print(word)
    ##print(word_type)
   
    if (word_type == None) and number_check(word):
          result.append(('number',int(word)))
    elif word_type is not None:
          result.append((word_type,word))
    else:
          result.append(('error',word))
    return result

Yes that’s correct. In your failing example, you are asking Python to import the lexicon module from ex48 (location) and then load ‘lexicon’ which isn’t a module there, nor is there a class either.

I think the import approach is one of those things that seems confusing until you get it. Then it just clicks. It’s worth spending a bit of time on this import approach as it’s very common in all programming languages.

1 Like

Not to correct, only to clarify this for others who might be reading this in future: It doesn’t have to be a class (though it mostly is). You can import anything that has a name in the respective module – classes, functions and variables.

By the way, thanks for posting the link above @gpkesley, that article cleared up a few things for me too. Looks like I’ve been using relative imports way too much. :slight_smile:

1 Like

Good call @florian - that’s worth pointing out its not limited to Class imports. You can see a good example of this with

from nose.tools import *

…although Python stylistas will shout at the use of the wildcard, but you can grab anything from tools.

So let’s look at this:

from ex48.lexicon import lexicon

That says, translated to English:

“Python, go into the ex48 directory, open the lexicon.py file, and import the lexicon (variable, function or class).”

Now, looking in your lexicon.py file what do you have:

def number_check
def scan
def data

Nothing in there is named “lexicon” but you said:

“Python, go INTO ex48/ then go INTO lexicon.py and FROM INSIDE THAT FILE import anything named ‘lexicon’”.

Your lexicon.py file doesn’t have anything named lexicon. If you only want scan, then you have to say this:

“Python, go INTO ex48/ then go INTO lexicon.py and FROM INSIDE THAT get me scan.”

from ex48.lexicon import scan

Now, if you just think about that as an English sentence it makes sense.

Here’s another example. Imagine you want to tell your little sister to go into the car’s glove box and get you the keys. You said this:

“Sister, go into our car and in there go into the glove box, and in that get me the glove box.”

Car is “ex48”, glove box is “lexicon.py” and you just asked your sister to get you the glove box from the glove box. Makes no sense right? You would actually say it like this:

“Sister, go into the car, and in the glove box, get me the keys.”

You could then just say:

“from the car glove box get me the keys”

And in python that’s:

from car.glove_box import keys

It’s pretty close to a succinct English way to say it. But you kept telling your Python Sister this:

from car glove_box get me the glove_box

Does that help?

1 Like

Folks,

I am having an issue with ex47 test part. I am getting an error of “instance of room has no path”. This error comes up when I add the “center.add_paths({‘north’: north, ‘south’: south})” part in the test file. I would be grateful for any help. Code and error message below.

from nose.tools import *

from ex47game import Room

def test_room():

    gold= Room("Gold Room", """This room has gold that you cangrab.

    there's a door to the North""")

    assert_equal(gold.name, "Gold Room")

    assert_equal(gold.path, {})

def test_room_path():

    center = Room("center", "Test room in the centre.")

    north = Room("North", "Test room in the North")

    south = Room("South", "Test room in the south")

    center.add_paths({'north': north, 'south': south})

That linter message means that the method you’re calling doesn’t exist.
Is it a simple spelling error? In your screenshot you call center.add_path(...) but in the code you posted it’s center.add_paths(...)?

from Myheart import ThankYou

Hi florian,

I have fixed the spelling error but seem to still have the same error.

from nose.tools import *

from ex47game import Room

def test_room():

    gold= Room("Gold Room", """This room has gold that you cangrab.

    there's a door to the North""")

    assert_equal(gold.name, "Gold Room")

    assert_equal(gold.paths, {})

def test_room_path():

    center = Room("center", "Test room in the center.")

    north = Room("North", "Test room in the North")

    south = Room("South", "Test room in the south")

    center.add_paths({'north': north, 'south': south})

also with the other file

class Room ():

    def __init__(self , name, description):

        self.name = name 

        self.description = description

        self.paths={}

def go(self, direction):

    return self.paths.get (direction, None)

def add_paths (self, paths):

    self.paths.update(paths)

Now I appreciate how difficult trying to trouble shoot what you can’t see so please let me know if you need more information from me.

Figured it out. I had the wrong indentation on the def file. Nonetheless, much appreciate the help.

1 Like