Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 807
  • Last Modified:

Calling a python method from a class

I've tried reading the python docs on classes, objects and data models but I still don't get it - I suppose that advanced programmers need to write classes but for what I'm able to do, writing a class seems to make things more difficult than they need to be.

I'm trying to write a program that requires me to create an instance of a 'Dog' class with the dog's name and breed as arguments, and append the object to the dogs list. For each user input on the name and breed, the current dogs list should print the name and breed of each dog, example:
#DOGS
0. Snoopy:Beagle
1. Marmaduke:Great Dane
2. Rover:Mutt

I can't figure out how to call the function so I'm not sure if the problem is with the way I'm trying to call the function or the way that I've written the methods in the class. Some of the guidance was fairly specific, for example the init() method should take two parameters, name and breed, in addition to the implicit self.  

I've copied the errors below with the offending code, and I don't understand the errors (if I did, I suppose I could fix this).

class Dog:

    def __init__(self, name, breed):
        self.name = 'Dog Name'
        self.breed = 'Dog Breed'
        self.dog_list = []

    # because 'dogs' in add_dog(**dogs) turned out to be undefined,  
    # not sure why...
    def keywords_as_dict(**dogs):
        return dogs
       
    def add_dog(**dogs):
	while True:
            try:
                name = raw_input("Enter dog name: ")
                breed = raw_input("Enter dog breed: ")

    		for name, breed in dogs.items():
            	    my_dog = (name.capitalize() + ": " + breed.capitalize())
                    print(my_dog)
                    dog_list.append(my_dog)
	    
	    except name == '':
                print('Exiting program')

        return dogs, dog_list
                           
if __name__ == "__main__":
    zero = Dog(name='Lassie', breed='Retriever') # or 
    one = Dog('Lassie', 'Retriever')
    print(zero, one) 
    # prints <__main__.Dog instance at some hex code> for each
    Dog.add_dog(one) # type error, method takes 0 args 
    Dog.add_dog() # or
    Dog.add_dog('Goofy', 'mutt') # or 
    Dog.add_dog(name='Goofy', breed='mutt') # type errors,
    # unbound methods must be called with class instance as first argument

Open in new window

0
sara_bellum
Asked:
sara_bellum
  • 6
  • 3
  • 2
4 Solutions
 
HonorGodCommented:
To start with, part of your problem is related to trying to have the "list" the way you do.

Let's start simply, and just define a class Dog that has a constructor which saves the dogs name and breed.
>>> class Dog :
...   def __init__( self, name, breed ) :
...     self.name = name;
...     self.breed = breed;
...
>>> lassie = Dog( 'Lassie', 'collie' )
>>>
>>> print lassie.name
Lassie
>>> print lassie.breed
collie
>>>

Open in new window

0
 
HonorGodCommented:
We could use this class to save information about individual dogs. but we really should have a "getter" to access the instance attributes;

Maybe something like:

----------
>>> execfile( 'dog.py' )
>>> a = Dog( 'Bubba', 'mixed' )
>>> print a.getName()
Bubba
>>> print a.getBreed()
mixed
>>>
>>> kennel = [ a, Dog( 'Li', 'Pug' ) ]
>>> for dog in kennel :
...   print dog.getName(), dog.getBreed()
...
Bubba mixed
Li Pug
>>>

class Dog() :
   def __init__( self, name, breed ) :
     self.name = name;
     self.breed = breed;
   def getName( self ) :
     return self.name;
   def getBreed( self ) :
     return self.breed;

Open in new window

0
 
HonorGodCommented:
Oh, using your examples:


>>> execfile( 'dog.py' )
>>> kennel = [ Dog( 'Snoopy' ,'Beagle' ), Dog( 'Marmaduke', 'Great Dane' ), Dog( 'Rover', 'Mutt' ) ]
>>> for i in range( len( kennel ) ) :
...   print '%d. %s:%s' % ( i, kennel[ i ].getName(), kennel[ i ].getBreed() );
...
0. Snoopy:Beagle
1. Marmaduke:Great Dane
2. Rover:Mutt
>>>

Open in new window

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
SuperdaveCommented:
Some problems with what you've got:
__init__ doesn't do anything with its arguments
add_dog doesn't do anything with the input it asks for
The methods keywords_as_dict and add_dog should both have self as the first argument.
Line 30: the Dog constructor takes two arguments (name and breed).
Lines 34-37: Dog is a class, not an instance.
0
 
SuperdaveCommented:
Here's a fixed-up version of what I think you were trying to do
class Dog:

    def __init__(self, name, breed):
        self.name = 'Dog Name'
        self.breed = 'Dog Breed'
        self.dog_list = []

    # because 'dogs' in add_dog(**dogs) turned out to be undefined,  
    # not sure why...
    def keywords_as_dict(**dogs):
        return dogs
       
    def add_dog(**dogs):
	while True:
            try:
                name = raw_input("Enter dog name: ")
                breed = raw_input("Enter dog breed: ")

    		for name, breed in dogs.items():
            	    my_dog = (name.capitalize() + ": " + breed.capitalize())
                    print(my_dog)
                    dog_list.append(my_dog)
	    
	    except name == '':
                print('Exiting program')

        return dogs, dog_list
                           
if __name__ == "__main__":
    zero = Dog(name='Lassie', breed='Retriever') # or 
    one = Dog('Lassie', 'Retriever')
    print(zero, one) 
    # prints <__main__.Dog instance at some hex code> for each
    Dog.add_dog(one) # type error, method takes 0 args 
    Dog.add_dog() # or
    Dog.add_dog('Goofy', 'mutt') # or 
    Dog.add_dog(name='Goofy', breed='mutt') # type errors,
    # unbound methods must be called with class instance as first argument

Open in new window

0
 
sara_bellumAuthor Commented:
I think I understand HonorGod's code, thanks very much!

But I can get the required output with the code below - I'm still very confused about how to construct a class to do the same thing. I'll have to think about that some more, it's late and another long day tomorrow.
if __name__ == "__main__":
    
    kennel = []
    while True:
        name = raw_input("Name: ")
        if name != '':
            breed = raw_input("Breed: ")
            my_dog = (name.capitalize() + ": " + breed.capitalize())
            kennel.append(my_dog)
            print('DOGS')
            for i,  my_dog in enumerate( kennel ):
                print str(i) + '.',  my_dog
            print('*' * 20) 
        else:
            print('*' * 20)
            sys.exit()

Open in new window

0
 
HonorGodCommented:
Line 8 doesn't create a "Dog"

instead of:

my_dog = (name.capitalize() + ": " + breed.capitalize())

You need something like:

my_dog = Dog( name.capitalize(), breed.capitalize() );

How about something like:
class Dog() :
  def __init__( self, name, breed ) :
    self.name = name;
    self.breed = breed;
  def getName( self ) :
    return self.name;
  def getBreed( self ) :
    return self.breed;

if __name__ == '__main__' :
  kennel = [];             # Create an empty list of dogs
  while True :
    name = raw_input( ' Name: ' ).strip();
    if name :
      breed = raw_input( 'Breed: ' ).strip();
      if breed :
        kennel.append( Dog( name.capitalize(), breed.capitalize() ) );
    else :
      break;
  print '\nDogs:\n' + ( '-' * 40 );
  for i in range( len( kennel ) ) :
    dog = kennel[ i ];
    print '%d. %s:%s' % ( i, dog.getName(), dog.getBreed() );

else :
  print "Error - execute this script, don't import it.\n";
  print 'python %s.py' % __name__;

Open in new window

0
 
HonorGodCommented:
Sample output:


C:\>python dog.py
 Name: Snoopy
Breed: Beagle
 Name: Marmaduke
Breed: Great Dane
 Name: Rover
Breed: Mutt
 Name:

Dogs:
----------------------------------------
0. Snoopy:Beagle
1. Marmaduke:Great dane
2. Rover:Mutt

Open in new window

0
 
SuperdaveCommented:
The class won't do much with such a simple example.  In HonorGod's example the class takes the place of a tuple of (name,breed) and doesn't do much more than a tuple would, except arguably make it more understandable because you access the elements by name GetName and GetBreed instead of [0] and [1].  In the example I modified from yours, the object takes the place of a list, and again doesn't really provide any more functionality, except you can add to it using named keywords instead of a tuple so it's maybe more understandable.  You could make an example that uses two classes, one for the list and one for the tuple, if you really wanted to demonstrate objects.
0
 
sara_bellumAuthor Commented:
Thanks - I appreciate your trying to take me through this one step at a time but in the end I just couldn't connect the dots...I'll get used to this, I'm sure of it :)
0
 
HonorGodCommented:
Thanks for the grade & points

Good luck & have a great day.
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 6
  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now