Calling functions from main python

17,039

Solution 1

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()

Solution 2

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.

Share:
17,039
jani
Author by

jani

I’m a SDET, programmer, dog-owner, backpacker, avid reader, DnD enthusiast, and amateur artist.

Updated on June 14, 2022

Comments

  • jani
    jani about 2 years

    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?

  • Peter Wood
    Peter Wood over 9 years
    But if you are using a class only as a namespace, why not just use a module?
  • Francis Colas
    Francis Colas over 9 years
    Well, I agree with you, but that's a question better asked to the OP who specifically wanted to do this.