Why is there a float in my string?

My code is here:
https://repl.it/@bennypr0fane/Tome-Rater

This is the Tome Rater project of the Python course.
I’m getting an attribute error after the class was populated (not sure if I’m saying that right) and I call one of the analysis methods:

>>> Tome_Rater.most_positive_user()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ben/Nextcloud/codn/programming-with-Python.Cdcdm/Projekte/TomeRater/TomeRater.py", line 182, in most_positive_user
    return get_keys_by_value(self.users, highest_rating)
  File "/home/ben/Nextcloud/codn/programming-with-Python.Cdcdm/Projekte/TomeRater/TomeRater.py", line 5, in get_keys_by_value
    if item[1] == value_to_find:
  File "/home/ben/Nextcloud/codn/programming-with-Python.Cdcdm/Projekte/TomeRater/TomeRater.py", line 28, in __eq__
    if self.name == other_user.name and self.email == other_user.email:
AttributeError: 'float' object has no attribute 'name'

I don’t understand here how a float end ups in here, it should be a string getting passed to this comparison: if self.name == other_user.name

Exactly the same problem as before:

Between lines 4 & 5, type this:
print(type(item[1]))
… and you get: <class 'classes.User'>

… which means that in line 5, you are using == to compare a User object with value_to_find, a float.

The use of == with a User object bounces you back to the User.__eq__() method …

… etc.

1 Like

Yeah, I fed the wrong thing into that function. The two things User and his average rating of a Book were connected in my head (as if I had mapped them together in a dictionary), but in the code, they are only connected by that function get_average_rating
Haven’t figured out yet how to go from the result (highest average_rating) to the User that got me that result.

Actually, it should be that User object’s name (item[0] corresponding to that item[1] ) that is compared, i. e. a string.

What is the method most_positive_user() supposed to do?

The users rate books they read. A user’s average rating of all the books s/he rated is calculated by user.get_average_rating(self, books).
most_positive_user() is supposed to return the user with the highest average rating.

I don’t see where you need the helper function, get_keys_by_value(). It’s a conventional max problem:

def get_average(t):    
    total = 0
    for i in range(len(t)):
        total += t[i]    
    return total / len(t)

def highest_average_letter(my_dict):
    max_average = 0
    high_letter = None       ##
    for letter in my_dict:        
        new_av = get_average(my_dict[letter])
        if new_av > max_average:
            max_average = new_av
            high_letter = letter      ##
    return letter
        

my_dict = {'a': (3,4,6,1), 'b': (1,6,0,-2), 'c': (3,3,8,1,0,1)}

print(highest_average_letter(my_dict))

# Output:
c

The lines marked ## are what I think you need to look at…

1 Like

These lines that you highlighted are pretty much it. Not exactly, but almost.
Your code would work without modification only if I had a dictionary with the users and their average ratings mapped together - which I could create, no doubt.
But it also works without that, doing exactly what you did there, and the helper function is indeed not needed.

def most_positive_user(self):
        print("Most positive user:")
        highest_rating = 0
        most_positive = None
        for user in self.users.values():
            average_rating = user.get_average_rating(user.books)
            if average_rating > highest_rating:
                highest_rating = average_rating
                most_positive = user
        return most_positive
1 Like

Thanks. I had just put in the dictionaries to simulate some of the other functionality in the class. Glad you got it working.