4

So I'm having a problem with a larger piece of code where I'm getting an error message when I'm calling a function inside of another function that is inside of a class. In the code:

#Test program to solve problems. 

class Foo(object):
    def __init__(self, number):
        self.number = number

    def run(self):
        print "I will now square your number"
        print "Your number squared is: "
        print self.calculate()

    #This squares the number
        def calculate(self):
            return self.number**2


if __name__ == "__main__":
    test = Foo(input("Choose a number: "))
    print test.run()

I raise an "AttributeError: Foohas no attribute calculate", but I don't understand why? Am I calling calculate wrong to throw this error?

EDIT

So I know that if I change the indentation or calculate it works, but I wanna know is there anyway to get it working as it currently is with calculate indented in run or do python classes not work that way.

1
  • Your indent level is off when you are defining calculate. Commented Aug 13, 2014 at 18:48

5 Answers 5

5

Updated after question edit:

Check out this link that shows how to make a "closure" https://stackoverflow.com/a/4831750/2459730

It's what you described as a function inside of a function.

def run(self):
    def calculate(self): # <------ Need to declare the function before calling
        return self.number**2

    print "I will now square your number"
    print "Your number squared is: "
    print self.calculate() # <---- Call after the function is declared

Before question edit: Your calculate function isn't indented properly.

def run(self):
    print "I will now square your number"
    print "Your number squared is: "
    print self.calculate()

#This squares the number
def calculate(self): # <----- Proper indentation
    return self.number**2 # <------ Proper indentation

The calculate function should have the same indentation level as the run function.

Sign up to request clarification or add additional context in comments.

5 Comments

Doesn't he want the function inside the function?
No, he just wants to call it from another function inside of the same class.
No I actually want calculate() inside run(). In my actual the body of calculate is dependent on run.
@Flameancer OK well your question said otherwise, if that's the case then you should edit your question to be more clear.
@Andrew_CS thanks to pointing me to closure. This was exactly what I was looking for. This code and my actual code works perfect now.
3

Indentation level is off. You are defining calculate INSIDE of the run function instead of in the class.

class Foo(object):
    def __init__(self, number):
        self.number = number

    def run(self):
        print "I will now square your number"
        print "Your number squared is: "
        print self.calculate()

    #This squares the number
    def calculate(self): #NOTE THE INDENTATION DIFFERENCE
        return self.number**2


if __name__ == "__main__":
    test = Foo(input("Choose a number: "))
    print test.run()

Comments

1

Seems you call function before it is defined. I think closure should help you:

def run(self):
    print "I will now square your number"
    print "Your number squared is: "

    def calculate():
        return self.number**2

    print calculate()

Comments

1

When you define a function inside a function then there is not need to use 'self' in inner function and call function after defining it. so you can write the code as,

class Foo(object):
    def __init__(self, number):
        self.number = number

    def run(self):
        #This squares the number
        def calculate():
            return self.number**2

        print "I will now square your number"
        print "Your number squared is: "
        print calculate()

if __name__ == "__main__":
    test = Foo(int(input("Choose a number: ")))
    print test.run()

Comments

0

The problem is just that you can't do that. It may seem tempting because you can outside of a class and it makes your code a littler cleaner, but within a class, you can't do it.

1 Comment

This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.