Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Viewing Party," - Shelby Faulconer, Ada C17 #119

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

pickled-bot
Copy link

…ss. Adjusted play_tester file by working through problems in the party file. All graveyard code lives in the play_tester. All test wave files were adjusted to comment out the skips.

…ss. Adjusted play_tester file by working through problems in the party file. All graveyard code lives in the play_tester. All test wave files were adjusted to comment out the skips.
Comment on lines 122 to 124
# *******************************************************************************************
# ****** Add assertions here to test that the correct movie was added to "watched" **********
# *******************************************************************************************

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a few tests with a comment similar to this where we would like you to add your own assertions. What could we assert about the data for a specific movie if we wanted to confirm that the movie in the "watched" list holds the information that we expect it to?

Comment on lines 145 to 147
# *******************************************************************************************
# ****** Add assertions here to test that the correct movie was added to "watched" **********
# *******************************************************************************************

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as for the test above, what could we assert about the three pieces of data a movie holds to confirm it is the movie we expect it to be?

@@ -59,7 +59,7 @@ def test_friends_unique_movies_not_duplicated():
# ****** Add assertions here to test that the correct movies are in friends_unique_movies **********

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert that came with the test lets us know how many movies to expect in the list friends_unique_movies, what can we assert to make sure the data each movie holds is correct?

@@ -57,7 +57,7 @@ def test_new_genre_rec_from_empty_friends():
# ****** Complete the Act and Assert Portions of theis tests **********

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this test we need to complete both the act & assert steps. What would that look like?

# If any of the three variables is missing, return None

from decimal import DivisionByZero
from tests.test_constants import USER_DATA_2

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally don't want production code to import or otherwise be dependent on test data. It doesn't look like this import is being used now, so we would want to clean it up so our program doesn't bring in resources it doesn't need.

def create_movie(title, genre, rating):
pass

if not title or not genre or not rating:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice use of the truthy/falsyness of the parameters for checking invalid input!


if not title or not genre or not rating:
return None
else:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's nothing wrong with it, but we don't need to put this code in an else-block as long as it comes after the if-statement that checks for invalid data.

Comment on lines 51 to 54
for movies in user_data["watchlist"]:
if movies["title"] == title:
user_data["watchlist"].remove(movies)
user_data["watched"].append(movies)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now we continue iterating over the watchlist after we perform our swap. In most cases this isn't a big deal, but say we were dealing with lists of thousands of movies. We would probably want to exit the loop right after we perform the operation we want, or we'll continuing to loop over potentially hundreds of more titles! How would we be able to halt execution once we performed our swap?

Another consideration: we are removing a value from a list we are actively iterating over, so after the first removal, we skip a value because the way iterators work (recall our discussion on the "danger zone" from the roundtable on "Iterating over Data"). Given the data for our tests, we know this isn't a concern for this application, but what if we were working with data that had duplicate titles?

Comment on lines 71 to 89
# { 'watched': [ { 'genre': 'Fantasy',
# 'rating': 4.8,
# 'title': 'The Lord of the Functions: The Fellowship of '
# 'the Function'},
# { 'genre': 'Fantasy',
# 'rating': 4.0,
# 'title': 'The Lord of the Functions: The Two '
# 'Parameters'},
# { 'genre': 'Fantasy',
# 'rating': 4.0,
# 'title': 'The Lord of the Functions: The Return of the '
# 'Value'},
# { 'genre': 'Action',
# 'rating': 2.2,
# 'title': 'The JavaScript and the React'},
# {'genre': 'Intrigue', 'rating': 2.0, 'title': 'Recursion'},
# { 'genre': 'Intrigue',
# 'rating': 4.5,
# 'title': 'Instructor Student TA Manager'}]}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally want to remove coding aids like this example data as part of our refactor and clean up steps.

watched_movies = user_data["watched"] ## array of dictionaries
total_rating = []
counter = 0
## for a dictionary in the list of movies

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As part of cleaning up code at the end, I recommend either removing the comments like this and the one above on line 93, or rewriting them to describe what the code is doing conceptually. For example, we might change this one to something like "loop over dictionaries representing movies to sum rating"

counter = 0
## for a dictionary in the list of movies
for movie_data in watched_movies:
v = movie_data["rating"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid single letter variables names in favor of ones that describe what our data represents. Some names we could use that would help readability might be "movie_rating", "rating", or "current_rating".

for movie_data in watched_movies:
v = movie_data["rating"]
total_rating.append(v)
if len(total_rating) == 0:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The preferred syntax for checking if a list is empty in python is to use the truthy/falsyness of the list (just like the input validation for create_movie above!)

    if not total_rating:

Comment on lines 107 to 123
## def function to track most watched genre
## COUNT of times genre appears
## If there is no amount, return error message
# '''
# input: take in the parameter 'user_data' : a nested dictionary
# with a VALUE 'watched' list of movie dictionaries
# each movie has the KEY "genre"
# >> this VALUE represents user's list of watched movies
# >> each watched movie contains a genre
# >>>> the VALUES of KEY "genre" is a string
# create a COUNTER to count which "genre" occurs most often
# If the value of "watched" is empty, return None

# output: The string of the genre that is most frequently watched,
# if value of watched is an empty list could try ... else none

# '''

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to keep detailed info for a function like this, we should use docstring syntax, by moving it inside the function right under the function name and removing the leading # characters. I would also strongly consider rewriting or condensing portions so that it reads more like spoken language. Here's more info on docstrings in case it's helpful: https://peps.python.org/pep-0257/

popular_genre = []
count = 0

if watched_movies == []:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to line 100, the preferred way to check if our watched_movies list is empty would be if not watched_movies:

for movie_data in watched_movies:
popular_genre.append(movie_data["genre"])
for movie_data in watched_movies:
if count < popular_genre.count(movie_data["genre"]):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice use of count! What would this implementation look like without the count function?

for movie_data in watched_movies:
if count < popular_genre.count(movie_data["genre"]):
count = popular_genre.count(movie_data["genre"])
return popular_genre[0]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we are returning the first item in popular_genre, which may or may not be the user's most watched genre. We have a count variable that finds the highest count of any of the genres, if we declared another variable before the loop that would hold the most popular genre we could do something like:

most_popular_genre = ""
.
.
.
for movie_data in watched_movies: 
    genre_count = popular_genre.count(movie_data["genre"]
    if count < genre_count):
        count = genre_count
        most_popular_genre = movie_data["genre"]

return most_popular_genre


def get_most_watched_genre(user_data):
watched_movies = user_data["watched"]
popular_genre = []

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be a good exercise to look at how this could be implemented differently with a dictionary instead of a list. What if we built up a mapping using genres for keys with their counts for values?

dictionary_friend_movies = []
unique_user_movies = []

for movie_watched in friends_list:
Copy link

@kelsey-steven-ada kelsey-steven-ada Mar 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way this is named, my initial instinct was that movie_watched would be a specific movie's dictionary. Since this is a dictionary holding a list of watched items, something plural like "friend_dict" or "movies_dict" would be a little more descriptive.

watched_movies = user_data["watched"]
friends_list = user_data["friends"]
user_watched = []
dictionary_friend_movies = []

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this structure is a list, it's a little misleading to name it starting with dictionary_ and might cause confusion for people trying to reason about what the variable holds. Since this list will hold all of the friends' movies, I think something like friends_movies would be descriptive enough.

unique_user_movies = []

for movie_watched in friends_list:
for movie in movie_watched["watched"]:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice choice to flatten the friends' movies into a single list you could check against!

for movie in movie_watched["watched"]:
dictionary_friend_movies.append(movie)
for movie in watched_movies:
user_watched.append(movie)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are appending values to user_watched here, but I don't see the list being used afterword. If they aren't being used, we should remove this line and the user_watched variable.

unique_friend_movies = []
unique_unique = []

for movie_watched in friends_list: # {} in [{}]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on line 150 applies here as well.


for movie_watched in friends_list: # {} in [{}]
for movie in movie_watched["watched"]:
if movie not in unique_friend_movies:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since set data structures cannot contain duplicates, how could we use them here where we want to find unique items?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could copy the movie_watched["watched"] data into a set and check to see if the set has changed length.

for movie in movie_watched["watched"]:
if movie not in unique_friend_movies:
unique_friend_movies.append(movie)
if movie in unique_friend_movies and movie not in watched_movies:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about sets more, say our unique_friend_movies and watched_movies were sets. We could then use set operations to find the difference - all the items in set a (unique_friend_movies) that are not in set b (watched_movies).

def get_available_recs(user_data):
movie_rec = []
watched_movies = user_data["watched"]
unique_movie_friends = get_friends_unique_watched(user_data)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 Love to see code reuse! 🎉

Comment on lines +189 to +192
for movie in unique_movie_friends:
if movie["host"] in user_subscriptions and movie not in watched_movies:
movie_rec.append(movie)
return movie_rec

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice & compact solution!

Comment on lines +201 to +202
popular_genre = get_most_watched_genre(user_data)
unique_movie_friends = get_friends_unique_watched(user_data)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yesss, reusing those functions!

Comment on lines +217 to +219
for movie in friends_list:
for watched_movie in movie["watched"]:
friend_watched.append(watched_movie)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We perform this task of condensing all the friend's movies into a single list in a few functions. This makes it a prime candidate to be pulled out to its own function for reuse!

@kelsey-steven-ada
Copy link

Congrats on completing your first project in Unit 1! I've added some suggestions and a couple questions, let me know if there's anything I can clarify.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants