4

I literally just started learning Python this week. (I will be a computer science fresher in a month!)

Here's a function I wrote to compute the square root of x.

#square root function

def sqrt(x):
    """Returns the square root of x if x is a perfect square.
Prints an error message and returns none if otherwise."""

ans = 0
if x>=0:
    while ans*ans <x:
        ans = ans + 1
        if ans*ans == x:
            print(x, 'is a perfect square.')
            return ans
        else:
            print(x, 'is not a perfect square.')
            return None    
else: print(x, 'is a negative number.')

But when I save it and type sqrt(16) into the Python shell, I get an error message.

NameError: name 'sqrt' is not defined

I'm using Python 3.1.1. Is there something wrong with my code? Any help would be appreciated. Thanks

UPDATE Okay, thanks to you guys I realized I hadn't imported the function. And when I tried to import it, I got an error because I saved it in a generic My Documents file instead of C:\Python31. So after saving the script as C:\Python31\squareroot.py, I typed into the shell (having restarted it):

import squareroot

And got a NEW error!

>>> import squareroot
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    import squareroot
  File "C:\Python31\squareroot.py", line 13
    return ans
SyntaxError: 'return' outside function

Meaning there WAS a bug in my original code! I'm going to look at some of the suggested corrections below right now. If you've spotted anything else, say. Thanks :)

UPDATE 2 - IT WORKED!!!!!!!!!!

Here's what I did. First, I used a cleaned up version of code kindly posted by IamChuckB. I made a new script with this in it (changed the function name from sqrt to sqrta to differentiate):

def sqrta(x):
    """Returns the square root of x if x is a perfect square.
Prints an error message and returns none if otherwise."""
    ans = 0
    if x>=0:
        while ans*ans <x:
            ans = ans + 1
        if ans*ans == x:
            print(x, 'is a perfect square.')
            return ans
        else:
            print(x, 'is not a perfect square.')
            return None    
    else: 
            print(x, 'is a negative number.')

And, importantly, saved it as C:\Python31\squareroota.py (Again, added an "a" at the end to differentiate between this the other, failed, file.)

Then I reopened Python shell and did this:

>>> import squareroota

Nothing happened, no error, great! Then I did this:

>>> squareroota.sqrta(16)

And got this!

16 is a perfect square.
4

Wow. I know this might seem like playing with ABC blocks in school but it honestly blew my mind. Thank you very much everyone!

rink.attendant.6
  • 44,500
  • 61
  • 101
  • 156
user1639304
  • 41
  • 1
  • 4
  • You can just use `ans ** 0.5`, you know. – Waleed Khan Aug 31 '12 at 17:20
  • 3
    You'll have to describe your workflow. What you mean by Python shell, how you run the shell, what you do between saving it to a file and trying it in the shell, what you did to make `sqrt` available in the shell, etc. –  Aug 31 '12 at 17:20
  • 2
    did you save this code in a file? did you import this in python shell? (sorry for asking those questions) – gizmo Aug 31 '12 at 17:21
  • Indentation matters in Python, so please make sure that the code that you have given is formatted _exactly_ like the code in question. – voithos Aug 31 '12 at 17:23
  • My exact process: I opened up the Python IDLE program, made a new blank window, typed the code, saved it in My Documents as function_sqroot.py, returned to IDLE, saw the >>> sign, typed sqrt(16), got an error. – user1639304 Aug 31 '12 at 17:27
  • Wait - I need to IMPORT it? Can't I just save it and call the function by typing it? – user1639304 Aug 31 '12 at 17:28
  • If you define the function in the interactive interpreter, you can call it this way from the interactive interpreter. If you define the function in a .py source file, you can call it that way from within the source file. To call the function from the interactive interpreter if it was defined in a source file, however, you would need to import it. – chucksmash Aug 31 '12 at 17:43
  • 1
    Indent everything after the `def sqrt(x):` line. – Russell Borogove Aug 31 '12 at 18:03
  • @arxanas Yeah I know, but I wanted to do it in terms of basic operations. Thought it would be a good way to practice looping. – user1639304 Aug 31 '12 at 18:27

4 Answers4

4

Yes I believe you have to actually import your function into the shell.

from yourfile import sqrt

Be careful. I think if you're in the shell and you make changes, you have to reimport your function for those changes to show up. As delnan mentions below you can reload your file after changeing it..

dm03514
  • 54,664
  • 18
  • 108
  • 145
  • 3
    Also, simply `import`-ing `yourfile` another time during the same session will not work. You need [`reload`](http://docs.python.org/py3k/library/imp.html#imp.reload) for that. –  Aug 31 '12 at 17:26
  • I closed and reopened the program, typed: >>> from C:\Users\Win 7\Documents\Python\function_squareroot.py import sqrt -and got another error- SyntaxError: invalid syntax – user1639304 Aug 31 '12 at 17:33
  • @user1639304, you need to let Python decide where to load from using the Python Path. And delnan is correct about needing `reload` when you make changes, see http://stackoverflow.com/questions/11618687/why-cant-you-re-import-in-python – Mark Ransom Aug 31 '12 at 17:37
  • Thanks! But when I typed >>>import sys there is no option to add the file anywhere - sorry to be such a n00b but could you tell me exactly how I can add the file to the list sys.path? – user1639304 Aug 31 '12 at 17:46
1

Firstly, your loop will always end on its first iteration since you essentially have if (...) return else return. Try this instead:

def sqrt(x):
    """Returns the square root of x if x is a perfect square.
       Prints an error message and returns none if otherwise."""
    ans = 0
    if x >= 0:
        while ans * ans <= x:
            if ans * ans == x:
                print(x, 'is a perfect square.')
                return ans
            ans = ans + 1
        print(x, 'is not a perfect square.')
        return None  
    else: print(x, 'is a negative number.')

But note that Python offers a built-in power operator:

def sqrt(x):
    return x ** 0.5 

To answer your question specifically, you will have to import your function. If the file in which this is written is sqrt.py, to use this function in another file you would need from sqrt import sqrt.

arshajii
  • 127,459
  • 24
  • 238
  • 287
0

The NameError means that your python shell does not recognize the function. You probably forgot to import the script.

Assuming that you saved your file as myscript.py (in the same directory as where you start your python shell), you have to use:

import myscript

for the functions defined inside to be available. Note that you'll have to call myscript.sqrt in order to run your function sqrt: it is only available in the myscript namespace.

An alternative is to type from myscript import sqrt: in that case, you make your myscript.sqrt available in the namespace as sqrt. Be careful that you don't overwrite a builtin function with this from ... import ......

Pierre GM
  • 19,809
  • 3
  • 56
  • 67
  • My function is named sqrt, but I saved the file as function_squareroot.py . I just did this: >>> import function_squareroot -but got- ImportError: No module named function_squareroot :( – user1639304 Aug 31 '12 at 17:36
  • Are you starting your python shell in the same directory where your file is saved? – Pierre GM Aug 31 '12 at 17:41
  • Err I don't think so. The shell gives an automatic option to save in the C:\Python31 folder, but I navigated instead to My Documents -_- – user1639304 Aug 31 '12 at 17:49
  • Is there somewhere I should save future files so I can just type import function_squareroot and the function will be automatically imported? – user1639304 Aug 31 '12 at 17:51
0

Here's your original code, just cleaned up so it will run. The problem with it as originally formatted was with indentation.

The while block should be indented one level (4 spaces) deep to denote it is in the def block for the function sqrt.

Having the if/else blocks inside of the while statements means that check is done each pass through the loop; therefore, the first time through when ans is only equal to one, that test will be done, your output with be printed and a value returned. We need to change this. Several of the other answers give more straight-forward ways to phrase this in python but, in keeping as close to the code you've written as possible, all you actually have to do is move the if block and the else block out of the while block. Code is shown below:

def sqrt(x):
    """Returns the square root of x if x is a perfect square.
Prints an error message and returns none if otherwise."""
    ans = 0
    if x>=0:
        while ans*ans <x:
            ans = ans + 1
        if ans*ans == x:
            print(x, 'is a perfect square.')
            return ans
        else:
            print(x, 'is not a perfect square.')
            return None    
    else: 
            print(x, 'is a negative number.')

Sample input and output are shown: In:

sqrt(9)

Out:

9 is a perfect square.

In:

sqrt(8)

Out:

8 is not a perfect square.

EDIT: In my opinion, Python is a great first language. When I was first starting off with it, I found the MIT OpenCourseWare class very useful. One very important note: the class is taught using Python 2.x instead of 3.x so some of the given code won't work right for you. Even if you don't watch all the video lectures, the assignments they give are of a reasonable difficulty and the reading assignments reference some excellent python learning materials.

The Udacity CS101 class also offers a good, directed introduction to programming in Python (and also uses Python 2.x) but I only worked through about half of the assignments there. I'd still recommend taking a look at it, however.

chucksmash
  • 5,777
  • 1
  • 32
  • 41
  • Also, thanks for the recommendations - I am currently watching the MIT OCW videos, and I have a few books, but once I finish these I will certainly take a look at Udacity. (Yeah, I found the differences between Python 2.x and 3.x were unsettling before I realised they were there - was seriously annoyed when `print 'stuff'` didn't work. Then I checked up the docs and saw my version of python makes the `print('stuff')` parentheses obligatory!) – user1639304 Aug 31 '12 at 18:24
  • @user1639304 Great! The MIT stuff is pretty fantastic. Unless you have a specific reason for using Python 3.x you might want to consider jumping down to Python 2.7.3 while you are learning unless you'll be taking a class taught in 3 this Fall or something similar. I believe you'll be able to find much more documentation targeted at learning in 2 and then once you're proficient with the language you can follow the from 2 to 3 guides. – chucksmash Aug 31 '12 at 18:37