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.

Flameancer
  • 97
  • 1
  • 2
  • 8

5 Answers5

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.

Community
  • 1
  • 1
Andrew_CS
  • 2,542
  • 1
  • 18
  • 38
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()
Tadgh
  • 1,999
  • 10
  • 23
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()
go1dshtein
  • 315
  • 1
  • 2
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()
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.

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/30578847) – holydragon Dec 14 '21 at 02:39