Boredless tourist: attractions_for_destination?


#1

I’ve been attempting to complete this project. I don’t understand the logic behind the function add_attraction(). Inside the function, we need to make a variable attractions_for_destination, append the value passed by attraction variable, and return nothing?

by that logic,

def add_attraction(destination, attraction):
  try:
    destination_index = get_destination_index(destination)  
    attractions_for_destination = attractions[destination_index]  
    attractions_for_destination.append(attraction)  
    return  
  except ValueError:  
    return

if I do this, because there is nothing that modifies attractions variable, every time attractions_for_destination = attractions[destination_index] is run, it will assign an empty list, I think? I honestly don’t understand the logic. why not append the attraction directly to the attractions list, like attractions[destination_index].append(attraction), instead of creating a variable attractions_for_destination?

PS: How do I properly add indentation? my whitespace is eaten.


#2

Hi @iamlearningjava

Regarding the indentation, you need to format your posted code. See How to ask good questions (and get good answers) for advice.

The add_attraction function adds an attraction to the attractions object, which is a list of lists. the function just needs to perform that action, and does not need to return anything in particular.

Each of the lists within attractions is a list of attractions for a particular destination. The list of attractions for each destination is located at an index that is the same as the index of that destination within the destinations list.

The add_attraction function uses the get_destination_index function to find the index of destination and saves it to destination_index. Then it uses that same index to access that destination's list of attractions within the attractions list. It saves a reference to that list to attractions_for_destination. Then it uses that attractions_for_destination reference to append the attraction to that destination's list of attractions.

If everything went well, then good, we have added an attraction for destination. If not, perhaps because we had an invalid destination or attraction, we have a ValueError, and nothing got added.


#3

I’m doing this project now and have the same question and I still don’t understand. Isn’t “attraction” only being appended to attrations_for_destination? why is it also being added to "attractions[destination_index]

Not sure if this is relevant but when I re-write the code without the “attractions_for_destination” variable at all, and instead just append “attractions” directly the output is the same. When the code is written this way it makes sense to me.


#4

I’m not sure if I understand your questions 100%, but I think I get the idea.

There are two lists in this project.

destinations = ["Paris, France", "Shanghai, China", "Los Angeles, USA", "So Paulo, Brazil", "Cairo, Egypt"]
attractions = [[], [], [], [], []]

attractions is a lists within a list. list at index 0 corresponds to Paris, France. List at index 1 corresponds to Shanghai,China.

So you need to make sure you’re adding the attraction to the correct corresponding destination. We do this by attractions[destination_index]. So if it is China it will identify the location to append attractions[ 1 ] and then append the attraction to the correct list. attractions[ 1 ].append(“Great Wall”)

attractions = [[], ["Great Wall"], [], [], []]

The only thing I’m not sure of is why we have variable “attractions_for_destination". I think you are right about that part. The .append() is a method and performs an action. Having a variable assigned to it does not make sense. Calling the variable does nothing. Maybe they had us write this variable so that we know what this part of the code is doing?

Here is a simple example I ran to prove this:

x = []
x.append(1)
y = x.append(2)

print(x)
print(y)

When you run the code…

>>> [1, 2]
>>> None

Does this answer your question?


#5

sort of, but I still don’t understand why the code is working as currently written.

If we are only appending “attraction” to the variable “attractions_for_destination” then why is “attraction” still showing up in the “attractions” list?


#6

That could explain it, yes. An intermediary variable is a means of observing a temporary value, as a value. In this case, skipping this step may be obvious for some, but not for others, who do not yet recognize the link up between destinations and attractions for destinations. It’s just more explicit and verbose.

The list.append() method is typeless, meaning it takes all values, regardless what type. Named values are still values (by reference), and may in some instances be dynamically derived, so can only be appended by name. In this particular example, one cannot argue for the use here beyond the above explaination… verbosity and explicitness.


#7

The attractions_for_destination variable points to the actual sub-list within attractions that corresponds to destination, rather than to a copy of that sub-list. Therefore, if you append an item to that sub-list, then you will see the item in there when you inspect the contents of attractions.

Below is an example that demonstrates that when you use a variable to access a sub-list, rather than to access a copy of that sub-list, any operation that you perform on the sub-list also applies to the list that contains that sub-list.

# we are responsible for feeding three cats
# each cat's record of feedings is stored in a sub-list
# numbers represent size of each feeding in spoonfuls
cat_feeding_sizes = [[4], [6, 7], [8, 2, 1]]

def feed_hungry_cat(cat_feeding_sizes, feeding_size):
    # feeding_size is in spoonfuls; feed it to hungriest cat
    least_total = sum(cat_feeding_sizes[0])
    index_of_hungriest_cat = 0
    # find cat that has been fed least total number of spoonfuls
    for cat_index in range(1, len(cat_feeding_sizes)):
        if sum(cat_feeding_sizes[cat_index]) < least_total:
            least_total = sum(cat_feeding_sizes[cat_index])
            index_of_hungriest_cat = cat_index
    # assign the sub-list of least-fed cat to hungriest_cat
    hungriest_cat = cat_feeding_sizes[index_of_hungriest_cat]
    # feed hungriest_cat; hungriest_cat variable accesses its sub-list
    hungriest_cat.append(feeding_size)


feed_hungry_cat(cat_feeding_sizes, 5)
feed_hungry_cat(cat_feeding_sizes, 9)
feed_hungry_cat(cat_feeding_sizes, 7)
feed_hungry_cat(cat_feeding_sizes, 6)
print(cat_feeding_sizes)

Output:

[[4, 5, 9], [6, 7, 6], [8, 2, 1, 7]]

Note that within these lines, a variable, hungriest_cat, is used to access and modify a sub-list:

    # assign the sub-list of least-fed cat to hungriest_cat
    hungriest_cat = cat_feeding_sizes[index_of_hungriest_cat]
    # feed hungriest_cat; hungriest_cat variable accesses its sub-list
    hungriest_cat.append(feeding_size)

Edited on January 12, 2019 to emphasize that the attractions_for_destination variable points to a particular sub-list within attractions rather than to a copy of that sub-list.