2

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?

3 Answers 3

4

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.

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

2 Comments

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

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

Comments

0

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

Comments

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.