CppLearner
CppLearner

Reputation: 17040

python unbound method again

This gets me into difficult time (sorry, i am still very new to python) Thank you for any kind of help.

The error

print Student.MostFrequent() TypeError: unbound method

MostFrequent() must be called with Student instance as first argument (got nothing instead)

This Student.MostFrequent() is called all the way in the end (last line) and the def is last def in the class

EDITED - Naming convention

My long code

import csv
class Student:
    sports = []
    ftopics = []
    stopics = []
    choice_list = []
    choice_dict = {}
    def __init__(self, row):
       self.lname, self.fname, self.ID, self.gender, self.sport, self.movie, self.movieyr, self.country, self.ftopic, self.stopic = row
       self.sports.append(self.sport)
       self.ftopics.append(self.ftopic)
       self.stopics.append(self.stopic)
    def print_information(self):
       return (self.lname, self.fname, self.ID, self.gender)
    def print_first(self):
       return (self.lname, self.fname, self.sport)
    def print_second(self):
        return (self.lname, self.fname, self.movie, self.movieyr)
    def print_third(self):
        return (self.lname, self.fname, self.country)
    def print_fourth(self):
        return (self.lname, self.fname, self.ftopic, self.stopic)
    def most_frequent(self):
        for choice in self.choice_list:
                self.choice_dict[choice] = self.choice_dict.get(choice, 0) + 1
        self.mostFrequent = sorted([(v, k) for k, v in self.choice_dict.items()], reverse=True)
        print self.mostFrequent

reader = csv.reader(open('new_mondy_csc_data_revise.csv'), delimiter=',', quotechar='"')
header = tuple(reader.next())
print "%-17s|%-10s|%-6s|%s" %header[:4]
print "-" * 45
students = list(map(Student, reader)) # read all remaining lines
for student in students:
    print "%-17s|%-10s|%-6s|%3s" % student.print_information()

print "%-17s|%-10s|%s" %(header[0],header[1],header[4])
print "-" * 45
for student in students:
    print "%-17s|%-10s|%s" %student.print_first()

print "%-17s|%-10s|%-16s|%s" %(header[0],header[1],header[5],header[6])
print "-" * 45
for student in students:
    print "%-17s|%-10s|%-16s|%s" % student.print_second()

print "%-17s|%-10s|%s" %(header[0],header[1],header[7])
print "-" * 45
for student in students:
    print "%-17s|%-10s|%s" %student.print_third()

print "%-17s|%-10s|%-15s|%s" %(header[0],header[1],header[8],header[9])
print "-" * 45
for student in students:
    print "%-17s|%-10s|%-16s|%s" % student.print_fourth()

k = len(students)    
# Printing all sports that are specified by students
for s in set(Student.sports): # class attribute
    print s, Student.sports.count(s), round(((float(Student.sports.count(s)) / k) *100),1)

# Printing sports that are not picked 
allsports = ['Basketball','Football','Other','Baseball','Handball','Soccer','Volleyball','I do not like sport']
allsports.sort()
for s in set(allsports) - set(Student.sports):
    print s, 0, '0%'
Student.choice_list = Student.sports
X = Student()
X.most_frequent()

#class Search(Student):
#    def __init__(self):
#        Student.__init__

Upvotes: 3

Views: 9839

Answers (7)

Jaime Soriano
Jaime Soriano

Reputation: 7359

What you probably want is to define most_frequent as a classmethod:

@classmethod
def most_frequent(cls):
    for choice in cls.choice_list:
        cls.choice_dict[choice] = cls.choice_dict.get(choice, 0) + 1
    cls.mostFrequent = sorted([(v, k) for k, v in cls.choice_dict.items()], reverse=True)
    return cls.mostFrequent

Upvotes: 2

mg.
mg.

Reputation: 8012

use Student().MostFrequent()

edit:

beware that you use class attributes and this is dangerous. here an example:

>>> class Person:
...  name = None
...  hobbies = []
...  def __init__(self, name):
...   self.name = name
... 
>>> a = Person('marco')
>>> b = Person('francesco')
>>> a.hobbies.append('football')
>>> b.hobbies
['football']
>>> a.name
'marco'
>>> b.name
'francesco'
>>> a.name = 'mario'
>>> b.name
'francesco'
>>> a.name
'mario'
>>> 

as you can see i modify marco's hobbies and francesco's hobbies are modified consequentially.

Upvotes: 7

miku
miku

Reputation: 188034

first read PEP-8 on naming conventions:

Method Names and Instance Variables

  Use the function naming rules: lowercase with words separated by
  underscores as necessary to improve readability.

second you are calling mostFrequest on the class Student, not an instance of it. Use the method on an instance instead:

student = Student(row)
student.MostFrequent()

Upvotes: 7

Johannes Charra
Johannes Charra

Reputation: 29923

First, I recommend making function names lower case only.

The error you get results from the usage of MostFrequent as a static method. For this to work, you need to explicitly pass an instance of Student as first argument.

If called directly on an instance of Student, the instance will implicitly be passed as first argument.

Consider using the staticmethod decorator for static usage of functions.

Upvotes: 1

Almad
Almad

Reputation: 5893

Student.MostFrequent means You're trying to use static method, not instance method. So You must first create instance by calling Student() and then call MostFrequent() on it.

P.S.: If this is not part of some arcane project, I urge you to follow PEP 8 and use most_frequent as method name.

Upvotes: 0

S.Lott
S.Lott

Reputation: 391854

You only rarely call methods on a class definition (Student)

Almost always, you create an instance of the class

someStudent = Student(someRow)

Then you call the method on the instance ("object"), someStudent.

someStudent.MostFrequent()

Upvotes: 0

Steve De Caux
Steve De Caux

Reputation: 1779

in your class def, the method definition

def MostFrequent(self,mostFrequent):

has the extra variable mostFrequent that you probably don't want there. Try changing to :

def MostFrequent(self):

Upvotes: -1

Related Questions