-
Notifications
You must be signed in to change notification settings - Fork 117
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
base: master
Are you sure you want to change the base?
Conversation
…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.
tests/test_wave_01.py
Outdated
# ******************************************************************************************* | ||
# ****** Add assertions here to test that the correct movie was added to "watched" ********** | ||
# ******************************************************************************************* |
There was a problem hiding this comment.
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?
tests/test_wave_01.py
Outdated
# ******************************************************************************************* | ||
# ****** Add assertions here to test that the correct movie was added to "watched" ********** | ||
# ******************************************************************************************* |
There was a problem hiding this comment.
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?
tests/test_wave_03.py
Outdated
@@ -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 ********** |
There was a problem hiding this comment.
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?
tests/test_wave_05.py
Outdated
@@ -57,7 +57,7 @@ def test_new_genre_rec_from_empty_friends(): | |||
# ****** Complete the Act and Assert Portions of theis tests ********** |
There was a problem hiding this comment.
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?
viewing_party/party.py
Outdated
# If any of the three variables is missing, return None | ||
|
||
from decimal import DivisionByZero | ||
from tests.test_constants import USER_DATA_2 |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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!
viewing_party/party.py
Outdated
|
||
if not title or not genre or not rating: | ||
return None | ||
else: |
There was a problem hiding this comment.
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.
viewing_party/party.py
Outdated
for movies in user_data["watchlist"]: | ||
if movies["title"] == title: | ||
user_data["watchlist"].remove(movies) | ||
user_data["watched"].append(movies) |
There was a problem hiding this comment.
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?
viewing_party/party.py
Outdated
# { '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'}]} |
There was a problem hiding this comment.
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.
viewing_party/party.py
Outdated
watched_movies = user_data["watched"] ## array of dictionaries | ||
total_rating = [] | ||
counter = 0 | ||
## for a dictionary in the list of movies |
There was a problem hiding this comment.
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"
viewing_party/party.py
Outdated
counter = 0 | ||
## for a dictionary in the list of movies | ||
for movie_data in watched_movies: | ||
v = movie_data["rating"] |
There was a problem hiding this comment.
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".
viewing_party/party.py
Outdated
for movie_data in watched_movies: | ||
v = movie_data["rating"] | ||
total_rating.append(v) | ||
if len(total_rating) == 0: |
There was a problem hiding this comment.
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:
viewing_party/party.py
Outdated
## 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 | ||
|
||
# ''' |
There was a problem hiding this comment.
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/
viewing_party/party.py
Outdated
popular_genre = [] | ||
count = 0 | ||
|
||
if watched_movies == []: |
There was a problem hiding this comment.
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:
viewing_party/party.py
Outdated
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"]): |
There was a problem hiding this comment.
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?
viewing_party/party.py
Outdated
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] |
There was a problem hiding this comment.
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 = [] |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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.
viewing_party/party.py
Outdated
watched_movies = user_data["watched"] | ||
friends_list = user_data["friends"] | ||
user_watched = [] | ||
dictionary_friend_movies = [] |
There was a problem hiding this comment.
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"]: |
There was a problem hiding this comment.
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!
viewing_party/party.py
Outdated
for movie in movie_watched["watched"]: | ||
dictionary_friend_movies.append(movie) | ||
for movie in watched_movies: | ||
user_watched.append(movie) |
There was a problem hiding this comment.
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 [{}] |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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! 🎉
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice & compact solution!
popular_genre = get_most_watched_genre(user_data) | ||
unique_movie_friends = get_friends_unique_watched(user_data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yesss, reusing those functions!
for movie in friends_list: | ||
for watched_movie in movie["watched"]: | ||
friend_watched.append(watched_movie) |
There was a problem hiding this comment.
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!
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. |
…ithin the function get_most_watched_genre().
…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.