Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

main method in Python

Tags:

python

I have the following code, which has the following two problems:

Traceback (most recent call last):
  File "C:\Users\v\workspace\first\src\tests.py", line 1, in <module> 
  class Animal:
  File "C:\Users\v\workspace\first\src\tests.py", line 39, in Animal

  File "C:\Users\v\workspace\first\src\tests.py", line 31, in main
    dog = Animal()
NameError: global name 'Animal' is not defined

This code is from a tutorial, and in the tutorial it works fine. I have the Python 2.7 and use the PyDev plugin for Eclipse.

  class Animal:
    __hungry = "yes"
    __name = "no name"
    __owner = "no owner"

    def __init__(self):
        pass

    def set_owner(self,newOwner):
        self.__owner= newOwner
        return

    def get_owner(self):
        return self.__owner

    def set_name(self,newName):
        self.__name= newName
        return

    def get_name(self):
        return self.__name

    def noise(self):
        print('errr')
        return

    def __hiddenmethod(self):
        print("hard to find")


    def main():
        dog = Animal()    
        dog.set_owner('Sue')
        print dog.get_owner()
        dog.noise()


    if  __name__ =='__main__':main()
like image 892
arnold leki Avatar asked Jan 10 '12 21:01

arnold leki


4 Answers

This code:

def main():
    dog = Animal()    
    dog.set_owner('Sue')
    print dog.get_owner()
    dog.noise()


if  __name__ =='__main__':main()

should not be in the class. When you take it outside (no indent) it should work.

So after taking that into account it should look like this:

class Animal:
    __hungry = "yes"
    __name = "no name"
    __owner = "no owner"

    def __init__(self):
        pass

    def set_owner(self,newOwner):
        self.__owner= newOwner
        return

    def get_owner(self):
        return self.__owner

    def set_name(self,newName):
        self.__name= newName
        return

    def get_name(self):
        return self.__name

    def noise(self):
        print('errr')
        return

    def __hiddenmethod(self):
        print("hard to find")


def main():
    dog = Animal()    
    dog.set_owner('Sue')
    print dog.get_owner()
    dog.noise()


if  __name__ =='__main__':
    main()
like image 158
kgr Avatar answered Nov 12 '22 07:11

kgr


To understand why what you wrote failed, you need to know a little bit about how class definitions work in Python. As you may know, Python is an interpreted language: there is a program which reads through Python files and executes them as it goes. When the interpreter encounters a class definition, it does the following:

  1. Creates a new namespace (record of all the variable names) in which the class variables and methods will be stored.
  2. Extracts all the code within the class definition (as determined by its indentation) and runs that code. This will populate the namespace which it just created.
  3. Creates a new class object whose namespace is that given above, and with base classes those given in the definition.
  4. Binds the name of the class to this object.

So what happened when you indented the main function inside your code? While inside step 2, you referred to the name Animal. But this name isn't defined until step 4! Indeed, it can't be defined at the stage you referred to it, because that would be circular. When you move main outside of the class definition, it won't be executed until after steps 1-4 have been completed, and hence the name Animal will already be bound.


By the way, the code you have written is not good Python. You should probably try to find a better tutorial; the usual recommendation is "Dive Into Python". I've rewritten it as it should be done:

  class Animal(object):
      def __init__(self, hungry="yes", name=None, owner=None):
          self.hungry = hungry
          self.name = name
          self.owner = owner

      def noise(self):
          print('errr')

      def _internal_method(self):
          print("hard to find")

  if  __name__ =='__main__':
      dog = Animal()    
      dog.owner = 'Sue'
      print dog.owner
      dog.noise()
like image 21
Katriel Avatar answered Nov 12 '22 09:11

Katriel


The following construct is worth having in most of your code - particularly if you are running in multiple environments.

if  __name__ =='__main__':
    main()
like image 2
lap Avatar answered Nov 12 '22 09:11

lap


Move both the main() method and the if __name__ == '__main__' statement out of the scope of the class. Remember - whitespace counts.

like image 1
Makoto Avatar answered Nov 12 '22 07:11

Makoto