2

I am trying to create a list objects that holds data about professional golfers. The different data points are golfer name and putting percentages from different distances. I want to sort this list of objects by name once all the data has been entered for every player object. The list of these objects is called PlayerNumber. When I try to sort PlayerNumber by attribute 'name'. I get an error stating that 'int' has no attribute and I am not sure why PlayerNumber is being referred to as an integer and not a list.

Any help would be appreciated. Here is the code:

import operator
import numpy as np
import statistics
import matplotlib.pyplot as plt
from colour import Color
from bs4 import BeautifulSoup
import urllib3

###############    ACCESS WEBPAGES       ####################
def makeSoup(url):
    http = urllib3.PoolManager()
    response = http.request('GET', url)
    soupdata = BeautifulSoup(response.data)
    return soupdata

siteURL = []
for i in range(7):
    siteURL.append(i)
siteURL[0] = ''
siteURL[1] = 'http://www.pgatour.com/stats/stat.408.html'   #>25
siteURL[2] = 'http://www.pgatour.com/stats/stat.407.html'   #20-25
siteURL[3] = 'http://www.pgatour.com/stats/stat.406.html'   #15-20
siteURL[4] = 'http://www.pgatour.com/stats/stat.405.html'   #10-15
siteURL[5] = 'http://www.pgatour.com/stats/stat.404.html'   #5-10
siteURL[6] = 'http://www.pgatour.com/stats/stat.02427.html' #3-5

###############    ACCESS TABLE DATA      ###################
def row_number(soupdata):
    for row in table.findAll('tr'):
        tot_row = row
    return tot_row

def parse_table(soupdata):
    currRank = []
    prevRank = []
    playerName = []
    rounds = []
    pctMake = []
    attempts = []
    puttsMade = []
    table = soupdata.find('tbody')
    tot_row = 0
    for row in table.findAll('tr'):
        #for col in row.findAll('td'):
        col = row.find_all('td')
        #column_1 = col[0]
        #currRank.append(column_1)
        #column_2 = col[1]
        #prevRank.append(column_2)
        column_3 = col[2].text
        column_3.strip()
        playerName.append(column_3)
        #column_4 = col[3]
        #rounds.append(column_4) 
        column_5 = col[4].text
        pctMake.append(column_5)            
        #column_6 = col[5]
        #attempts.append(column_6)    
        #column_7 = col[6]
        #puttsMade.append(column_7)
        tot_row += 1
    #return currRank, prevRank, playerName, rounds, pctMake, attempts, puttsMade
    return playerName, pctMake, tot_row

"""
>25 ft: distance1
20-25 ft: distance2
15-20 ft: distance3
10-15 ft: distance4
5-10 ft: distance5
3-5 ft: distance6
"""
###############    CLASS DEFINITION      ###################
class Player:
    id_list={}
    def __init__(self,name, id, dis1=0.0, dis2=0.0, dis3=0.0, dis4=0.0, dis5=0.0, dis6=0.0):
        self.name = name
        self.dis1 = dis1
        self.dis2 = dis2
        self.dis3 = dis3
        self.dis4 = dis4
        self.dis5 = dis5
        self.dis6 = dis6
        self.id = id
        Player.id_list[self.name] = self # save the id as key and self as he value
    def addDis1(self,distance1):
        self.dis1 = float(distance1)
    def addDis2(self,distance2):
        self.dis2 = float(distance2)
    def addDis3(self,distance3):
        self.dis3 = float(distance3)
    def addDis4(self,distance4):
        self.dis4 = float(distance4)
    def addDis5(self,distance5):
        self.dis5 = float(distance5)
    def addDis6(self,distance6):
        self.dis6 = float(distance6)
    def displayPlayer(self):
        print("Player: ", self.name, '\n'
              ">25 Ft %: ", self.dis1, '\n'
              "20-25 Ft %: ", self.dis2, '\n'
              "15-20 Ft %: ", self.dis3, '\n'
              "10-15 Ft %: ", self.dis4, '\n'
              "5-10 Ft %: ", self.dis5, '\n'
              "3-5 Ft %: ", self.dis6, '\n')
    @classmethod
    def lookup_player_name_by_id(cls, name):
        try:
            return cls.id_list[name] # return the instance with the id 
        except KeyError: # error check for if id does not exist
            raise KeyError("No user with id %s" % str(id))

###############    DATA POPULATION      ###################
PlayerNumber=[]
for i in range(0,195):
    PlayerNumber.append(i)
for i in range(1,7):
    soupdata = makeSoup(siteURL[i])
    playerName, pctMake, tot_row = parse_table(soupdata)
    for x in range(0,tot_row):
        #PlayerNumber.append(x)
        name = playerName[x]
        name = name.replace("\xa0", " ")
        name = name.replace("\n", "")
        if i == 1:
            PlayerNumber[x] = Player(name, x)
            Player.addDis1(PlayerNumber[x],pctMake[x])
        if i == 2:
            val = Player.lookup_player_name_by_id(name)
            Player.addDis2(PlayerNumber[val.id],pctMake[x])
        if i == 3:
            val = Player.lookup_player_name_by_id(name)
            Player.addDis3(PlayerNumber[val.id],pctMake[x])
        if i == 4:
            val = Player.lookup_player_name_by_id(name)
            Player.addDis4(PlayerNumber[val.id],pctMake[x])
        if i == 5:
            val = Player.lookup_player_name_by_id(name)
            Player.addDis5(PlayerNumber[val.id],pctMake[x])
        if i == 6:
            val = Player.lookup_player_name_by_id(name)
            Player.addDis6(PlayerNumber[val.id],pctMake[x])

PlayerNumber.sort(key = operator.attrgetter("name"))         
#PlayerNumber[2].displayPlayer()

I'm using Python 3.4 spyder IDE. I'm relatively new to python as an FYI.

Thanks!

5
  • x = 4; x.name - the code effectively does this. Why? Trust the error message and work backwards. Commented Sep 30, 2017 at 23:09
  • Isn't the integer x just referring to the index location of where the object is being stored within the list though? I don't understand where the code is trying to attach the attribute name to x. Commented Sep 30, 2017 at 23:28
  • What line is the .name on that throws the error? What is the value it was attempted to be called against? The error message says both of these. Why is the value an integer at this point? Commented Oct 1, 2017 at 22:20
  • 1
    You're right. I figured it out. The error was due to the website changing the number of rows of players so I was creating a list that exceeded the number of players to fill the list. So for the last cases of the list (i.e 192, 193 etc.) were just the ID numbers and not objects like the preceeding list indices. I made the list size change according to # of rows on the website so that error shouldn't occur again. Thanks for the help. Commented Oct 3, 2017 at 0:34
  • I'm glad the problem is solved! The "ah hah!" moment can be quite gratifying, if following measured steps to get there.. and it can be a very aggregating experience if not connecting the dots. Commented Oct 3, 2017 at 3:31

1 Answer 1

2

It isn't that PlayerNumber is being referred to as an integer, but rather that PlayerNumber is a list of integers, and every element of that list (and integer) doesn't has an attribute "name", which sort() is trying to access (in order to sort them).

Edit:

To elaborate, the second to last line in your sample:

PlayerNumber.sort(key = operator.attrgetter("name"))

is trying to sort PlayerNumber, using the comparison function: operator.attrgetter("name"), which means it must call that function on each element of PlayerNumber to get its rank in the sorted array. That is why you are trying to grab a .name attribute from the integers in PlayerNumber.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.