user2536262
user2536262

Reputation: 279

Python OOP Exercise

I'm trying to learn using classes in Python, and have written this test program. It is to some extent based on code I found in another question I found here on Stack OverFlow.

The code looks as follows:

class Student(object):
    name = ""
    age = 0
    major = ""

    # The class "constructor" - It's actually an initializer 
    def __init__(self, name, age, major):
        self.name = name
        self.age = age
        self.major = major
    def list_values():
        print "Name: ", self.name
        print "Age: ", self.age
        print "Major: ", self.major

def make_student(name, age, major):
    student = Student(name, age, major)
    return student

print "A list of students."
Steve = make_student("Steven Schultz",23,"English")
Johnny = make_student("Jonathan Rosenberg",24,"Biology")
Penny = make_student("Penelope Meramveliotakis",21,"Physics")
Steve.list_values()
Johnny.list_values()
Penny.list_values()

When I run this, get the error "TypeError: list_values() takes no arguments (1 given)". In my oppinion I have not given any arguments, but I remove the parenthesis, giving the code

Steve.list_values
Johnny.list_values
Penny.list_values

This renders no errors, but does not do anything - nothing gets printed.

My questions:

  1. What's the deal with the parenthesis?
  2. What's the deal with the print statements?

Upvotes: 1

Views: 4191

Answers (4)

Roland Smith
Roland Smith

Reputation: 43563

As others have mentioned, you should use self in list_values.

But you should really define one of the magic method __str__ or __repr__ instead. Additionally, you're setting some class properties that aren't necessary.

A simpler implementation would be:

class Student(object):

    def __init__(self, name, age, major):
        self.name = name
        self.age = age
        self.major = major

    def __str__(self):
        fs = "<name: {}, age: {}, major: {}>"
        return fs.format(self.name, self.age, self.major)

Use it like this:

In [9]: Steve = Student("Steven Schultz", 23, "English")

In [10]: Johnny = Student("Jonathan Rosenberg", 24, "Biology")

In [11]: Penny = Student("Penelope Meramveliotakis", 21, "Physics")

In [12]: print Steve
<name: Steven Schultz, age: 23, major: English>

In [13]: print Johnny
<name: Jonathan Rosenberg, age: 24, major: Biology>

In [14]: print Penny
<name: Penelope Meramveliotakis, age: 21, major: Physics>

Since you're not defining special methods, you might as well use a named tuple:

In [16]: from collections import namedtuple

In [17]: Student = namedtuple('Student', ['name', 'age', 'major'])

In [18]: Steve = Student("Steven Schultz", 23, "English")

In [19]: print Steve
Student(name='Steven Schultz', age=23, major='English')

Upvotes: 0

WeaselFox
WeaselFox

Reputation: 7400

Python requires you explicitly add the self arguments to member functions, you forgot to add self to your function decleration:

def list_values(self):

This defines it as a member function of the Student class. see here. When you call the functions as members of the Student instances, the self variable is added implicitly, thus triggering the exception, since you did not define a function named list_values that receives one parameter.

As for removing the parenthesis, this means you are not calling the functions but only referring to the function objects, doing nothing.

Upvotes: 1

ebarr
ebarr

Reputation: 7842

The list_values method needs to be bound to your Student instance:

You should change:

def list_values()

to:

def list_values(self)

For an explanation of why, see:

Also this blog post by Guido covers the subject too:

Upvotes: 1

wong2
wong2

Reputation: 35760

def list_values(): should be: def list_values(self):

In Python, instance methods take self as the first argument.

Upvotes: 0

Related Questions