jani
jani

Reputation: 107

Calling functions from main python

I have some python 3.4 code that works fine:

def run():
    m = 0
    while m != 1:    
        p = input('Please choose p: ')
        p = makeInt(p)
        #Some other code
        print(p)
        m = makeInt(input('Enter 1 if you would like to quit: '))

def makeInt(i):
    try:
        i = int(i)
    except ValueError:
        i = input('Incorrect input! Enter your answer: ')
        i = makeInt(i)
    return i

#Some other functions    

if __name__ == '__main__':
    run()

I want to put all this code in a class (Except possibly if __name__ ==...) When I put all the code including if __name__ ==... in a class like so:

class Foo(object):
    def run(self):
        m = 0
        while m != 1:    
            p1 = input('Please choose p: ')
            p1 = self.makeInt(p1)
            #Some other code
            print(p1)
            m = self.makeInt(input('Enter 1 if you would like to quit: '))

    def makeInt(self, i):
        try:
            i = int(i)
        except ValueError:
            i = input('Incorrect input! Enter your answer: ')
            i = self.makeInt(i)
        return i
    #Some other functions and stuff

    if __name__ == '__main__':
        run()

I get the following error: TypeError: run() missing 1 required positional argument: 'self'. When I remove the self argument from run() it runs until makeInt() is called and then I get: NameError: name 'makeInt' is not defined. I get the same error if I take the if statement out of the class and call Foo.run(). I have some other code earlier in this program that works when I call functions of a class from another function in that same class. I realize I don't have to put all my code in a class, but in this case I want to. Why am I getting these errors and what can I do to put my working code in a class?

Upvotes: 2

Views: 27168

Answers (3)

Selcuk
Selcuk

Reputation: 59238

Since you wrap your code within a class, your run() is a method now. You should remove your main from your class by unindenting it and initialize an instance of your class:

if __name__ == '__main__':
    Foo().run()

Upvotes: 3

Francis Colas
Francis Colas

Reputation: 3647

As others mentioned, by putting your functions in a class, you've made them methods, that means they need an instance of this class as first argument. So you can indeed call your run method using Foo().run() as Foo() will create an instance of Foo.

Another way (e.g. if you don't need the class for anything else than encapsulation) is to make them static, using the staticmethod decorator:

class Foo(object):
    @staticmethod
    def run():
        ...

    @staticmethod
    def makeInt(i):
        ...

if __name__ == '__main__':
    Foo.run() # don't need an instance as run is static

In Python, a method can be static, i.e. no need for any special argument, a class method, i.e. first argument is the class itself, or a standard method, i.e. the first argument is an instance of the class.

Upvotes: 4

Josh Allemon
Josh Allemon

Reputation: 940

It thinks the guard is a part of your class due to the indentation: you have your guard indented to the same level as the other class members. Unindent the

if __name__ == '__main__'

Also change it to be

if __name__ == '__main__':
  main()

and then instantiate a new object of type Foo in your newly created main() function

def main():
  newFoo = Foo()
  newFoo.run()

Upvotes: 0

Related Questions