views:

512

answers:

8

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__
+2  A: 

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.

mg
does this work with a constructor like: def __init__(self, row)?
The MYYN
and how steve said remove the mostFrequent argument from the method definition, but the error you got is related to the fact that you don't instance the class
mg
@The MYYN: no. maybe i hastily answer the question but he gets that error because he calls a method over a class and not an object. to call a method over a class there are `classmethod` and `staticmethod` decorators. see the doc about their use.
mg
A: 

Hi,

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):
Steve De Caux
i guess in this case this would complain about wrong number of arguments, or not?
The MYYN
always nice to see a CS grad in a hissy fit
Steve De Caux
+1  A: 

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()
S.Lott
+3  A: 

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()
The MYYN
A: 

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.

Almad
A: 

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.

jellybean
A: 

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
Jaime Soriano
A: 

Thanks everyone. I just solved it but I decided to take it off because I found a better way.

JohnWong