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

Phoniex_C22_Tram_Beenish #10

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

Conversation

beenishali693
Copy link

No description provided.

if not title or not genre or not rating:
return None
movie_dict = {}
if type(title) == str and type(genre) == str and type(rating) == int or type(rating) == float or int:
Copy link
Author

@beenishali693 beenishali693 Sep 27, 2024

Choose a reason for hiding this comment

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

we noticed after we submitted but the or int at the end of the line is not needed.

Suggested change
if type(title) == str and type(genre) == str and type(rating) == int or type(rating) == float or int:
if type(title) == str and type(genre) == str and type(rating) == int or type(rating) == float:

Choose a reason for hiding this comment

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

Thanks for pointing this out. Including a check like this (though not required by the project prompt) can be helpful, as it can identify bad data before it gets into our objects. If we didn't have this check, Bad data could sneak into an object at some point, only to cause problems later on. Then we'd have to try to trace back to where the bad data came from.

Intersting, the or int literally does nothing here. It might be tempting to read the type(rating) == float or int as checking that rating is either an int or a float, with the earlier separate check for int making the or int redundant, but that's not what's happening. Instead, with the previous rating checks, it's more like this

(type(rating) == int) or (type(rating) == float) or (int)

and and or have lower precedence than the comparison operators, so they act to group together multiple entire comparisons, not multiple values within a comparison. So we have the two checks for the type of rating, anfd then or int off by itself. It turns out that if rating is an int or float, the the interpretation of int on its own doesn't matter. If the value on the left of or is truthy, it doesn't even try to evaluate the value on the right. But if the value on the elft is falsy, it does need to evaluate this. It turns out that all "types" (like int) are truthy, so this is like having or True stuck on the end. This has the effect of deactivating the float and int type checks, because even if rating is neither a float nor an int, the final or int will cause that check to pass.

So even more than not being needed, the or int check is causing a problem.

One thing to watch out for in a more general case is that explicit type() checks can sometimes be overly strict. It's often preferred to do an isinstance check, whcih takes into account type inheritance in Python. In other cases, especially if we're not just storing the value to use later, we might just try to use the value without checking the type at all. If it works, it works. If not, hopefully an error gets raised on the part that's unsupported. This tends to be the most flexible thing to do to remain compatible with python's lack of static type checking.

Statically typed languages like the C language family, Java, and many others, do away with needing to perform checks like this by explicitly declaring the valid types of the parameters as part of the function definition. THe compiler would catch an attempt to pass in the wrong kind of data before even running the code.

Copy link

@anselrognlie anselrognlie left a comment

Choose a reason for hiding this comment

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

Looks good! Please review my comments, and let me know if you have any questions. Slack, our next 1:1, or office hours are preferred (rather than replying to my comments in GitHub) as I don't have email notifications turned on. Nice job!

# *******************************************************************************************
# ****** Add assertions here to test that the correct movie was added to "watched" **********
assert janes_data["watchlist"] == []

Choose a reason for hiding this comment

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

We probably don't need this check for the empty list, since we have an earlier check that the length of the watchlist is 0. Technically, this also ensures that the type of the collection is still a list, but it would be very surprising if that had changed.

Comment on lines +165 to +169
assert janes_data["watched"] == [{
"title": MOVIE_TITLE_1,
"genre": GENRE_1,
"rating": RATING_1
}]

Choose a reason for hiding this comment

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

👍 Great approach for checking all three pieces of data of the dict are the expected values. By building a temporary dict with the keys and values, the value comparison of the dictionary will take care of the value by value comparison.

Notice that we can only definitively know the location of the movie in the watched list because there's only a single item in the list. The project made no specification about where in the list items should end up when moving to the watched list.

Comment on lines +194 to +195
assert janes_data["watchlist"] == [FANTASY_1]
assert janes_data["watched"] == [FANTASY_2, movie_to_watch]

Choose a reason for hiding this comment

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

👍 Great idea to check that the contents that should not have been affect by the move are still in the expected lists.

Here, rather than literally checking that the 2 movies in the watched list are in the order listed here, we might prefer to use a few in checks. While it's true that your implementation will put a recently watched movie at the end of the list, that behavior is not in the specification.

Checking for more strict behaviors than are specified can tie our hands down the road if we wanted to perform some kind of refactoring later on that didn't maintain this same guarantee.

Comment on lines +61 to +63
assert INTRIGUE_3 in friends_unique_movies
assert HORROR_1 in friends_unique_movies
assert FANTASY_4 in friends_unique_movies

Choose a reason for hiding this comment

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

👍 Great way to check that the three movies are in the output.

Here, it's even more important not to assume a particular ordering of the outputs. The act of making some data unique can often result in data ending up in arbitrary locations relative to where they occurred in the original data, especially if intermediate data structures like sets or dicts are involved.

Comment on lines +55 to +59
#Act (completed by us)
recommendations = get_new_rec_by_genre(sonyas_data)

raise Exception("Test needs to be completed.")
# *********************************************************************
# ****** Complete the Act and Assert Portions of these tests **********
# *********************************************************************
# Assert(completed by us)
assert len(recommendations) == 0

Choose a reason for hiding this comment

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

👍 This test needed both the act and the assert.

Choose a reason for hiding this comment

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

Nit: leave a space after the # character in comments

    # Act (completed by us)

Comment on lines +111 to +115
recommendations = []
for movies in friend_unique_movies:
if movies["host"] in user_data["subscriptions"]:
recommendations.append(movies)
return recommendations

Choose a reason for hiding this comment

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

Code like this is an ideal candidate for a list comprehension. A list comprehension is a shorthand syntax for creating a new list, based on processing/filtering another list. This logic could be rewritten as

    return [movie for movie in friend_unique_movies if movie["host"] in user_data["subscriptions"]]

The first time we see this, it may feel more complicated, but it's a common enough pattern that we should get used to seeing/writing it.

def get_available_recs(user_data):
friend_unique_movies = get_friends_unique_watched(user_data)
recommendations = []
for movies in friend_unique_movies:

Choose a reason for hiding this comment

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

Nit: The loop variable should usually be a singular noun (so movie not movies) since it refers to each element in the collection one by one.

Comment on lines +120 to +122
recs = get_friends_unique_watched(user_data)
new_rec_by_genre = []
most_freq_genre = get_most_watched_genre(user_data)

Choose a reason for hiding this comment

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

👍 Another great reuse of previous wave functions!

Comment on lines +123 to +126
for movie in recs:
if movie["genre"] == most_freq_genre:
new_rec_by_genre.append(movie)
return new_rec_by_genre

Choose a reason for hiding this comment

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

Here's another great candidate for a list comprehension: the logic that builds a filtered list of movies to those sharing a genre with the most watched genre.


def get_rec_from_favorites(user_data):
rec_from_favorites = []
unique_watched = get_unique_watched(user_data)

Choose a reason for hiding this comment

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

👍 And here we can start from the unique list of user watched movies, then filter it down to those that also appear in the favorites list.

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.

3 participants