Python Crash Course exercise 8-11 - python-3.x

I am working through the Python Crash Course book by Eric Matthes and I am stuck on 8-11. I don't quite understand how to return the new list and store it in a separate list.
So far I have tried to call the function by making a copy of the list.
def make_great(magicians):
"""This function adds the 'The Great' in front of a magicians name"""
great_magicians = [] #A new list to hold names of new magicians
while magicians: #This while loop runs while the parameter 'magicians' has elements in it
magician = magicians.pop() #Element from magicians parameter held in magician varibale
great_magician = magician + " the Great" #Creating a new element to store great_magician
great_magicians.append(great_magician) #Adding great_magicians to empty list
for great_magician in great_magicians: #Adding elements in great_magician back into magicians
magicians.append(great_magician)
magician_names1 = ['inho','mumbo jumbo','trick shotta','hwolla']
make_great(magician_names1[:])

List are mutable, that is they can be modified. so return the modified list and save it under the variable name of - magician_names1
def make_great(magicians):
"""This function adds the 'The Great' in front of a magicians name"""
great_magicians = [] #A new list to hold names of new magicians
while magicians: #This while loop runs while the parameter 'magicians' has elements in it
magician = magicians.pop() #Element from magicians parameter held in magician varibale
great_magician = magician + " the Great" #Creating a new element to store great_magician
great_magicians.append(great_magician) #Adding great_magicians to empty list
for great_magician in great_magicians: #Adding elements in great_magician back into magicians
magicians.append(great_magician)
return magicians
magician_names1 = ['inho','mumbo jumbo','trick shotta','hwolla']
magician_names1 = make_great(magician_names1[:])
print(magician_names1)

Your current function modifies the list you pass it in place. That means if you call make_great(magician_names1), it will modify the names in your main list and you won't have access to the original values any more.
If you want to make the changes in a new list, there are two general approaches you can take. The first is to change the function so that it creates and returns a new list and does not modify the list you passed in to it. That's pretty easy:
def make_great(magicians):
return [magician + " the Great" for magician in magicians]
# or:
# results = []
# for magician in magicians:
# results.append(magician + " the Great")
# return results
When you call it, you can assign the returned list to a new variable, and the old list will remain the same: great_names = make_great(magician_names1)
The other option is to leave your current function alone, as you might sometimes want to do the modifications in place. In the cases you don't want that, you can first make a copy, then modify the copy in place:
great_names = magician_names1[:] # make a copy and give it a name
make_great(great_names) # then modify the copied list in place
I'll note that while your current code does work for the in place modification, it's a lot more complicated than it needs to be (it also reverses the order the names appear in the list, which may be an undesireable side effect). You can write a much simpler version using the enumerate builtin function to get the index of a name as you iterate over the list it was contained in:
def make_great(magicians):
for i, name in enumerate(magicians):
magicians[i] = name + " the Great"

Related

Python remove word from bigram in list without returning a new list

Just quick side question. Is there a way and if, how to remove/delete a specific word from a bigram in a list (must be the same list!) that also contains just words. E.g.
In:
x = ['Peter Parker', 'Hugo', 'Fischerman']
Task, delete Parker from that same list:
Expected output:
x as ['Peter', 'Hugo', 'Fischerman']
I tried to use xx = [x.replace('Parker, '') for x in xx]but it seems to give me a new list in the sack.
Any ideas?
list = ['Peter Parker', 'Hugo', 'Fischerman'] # initialize list
for item in range(len(list)): # loop
list[item] = list[item].replace("Parker", "").strip() # replace item nu=umber "item" with its fixed result, replacing "Parker" with nothing and stripping - this just does nothing if "Parker" is not in item number "item".
That should work, just omit the list initialization to add it wherever (and don't forget to fix the variable names!)

Flatten List of Lists Recursively

Can someone illustrate or decompose how this recursive function is executed
def flatten(S):
if S == []:
return S
if isinstance(S[0], list):
return flatten(S[0]) + flatten(S[1:])
return S[:1] + flatten(S[1:])
s=[[1,2],[3,4]]
print("Flattened list is: ",flatten(s))
How could I trace the execution of this algorithm?
Ok so this is a recursive function as you have stated. It is a mostly 'look at the next element and decide what to do with it' method. It is started with the base case.
if S == []:
return S
So this makes sense. You have an empty list, so you would expect to get back an empty list, it's flat.
if isinstance(S[0], list):
return flatten(S[0]) + flatten(S[1:])
Next is the first 'look at the next element, decide what to do', if I receive a list and at the first element there is a list, I will get the program to run this same flattening method on the first element.
But then comes the rest of the list, we don't know if that is flat so I will be doing the same thing for that calling flatten on that as well.
When this returns they should both be flat lists. Adding two lists just joins them together into a new list so this would be returned up a level to the previous call of the recursive method or return to the user.
return S[:1] + flatten(S[1:])
From before we know that the first element of the list is not a list as the if statement was if isinstance(S[0], list) so this is just taking a list with the first element stored in it and just like before running flatten on the rest of the list as we don't know whether the rest of the list is flat or not.
As for tracing, if you don't have Pycharm or pdb is to complex for you. Throw in some prints within each of the if statements. Don't be shy, you're the one that's going to read them. do a print(f"First element was a list: {S[0]}, {S[1:]}") that will be fine if you're a beginner dealing with such a small amount of code. Otherwise try PDB or such.

I want to add "100" in the list so used append method

Want to apply an append method in for loop to add new value to list but the result infinite none. I am new to programming. Below is my code.
a = [2, 3, "name",10]
for i in a:
app = a.append(100)
print(app)
append actually works by modifying the original list, rather than returning the list with the item appended. In fact, the function always returns None, as you have found. If you instead print the contents of the original list, i.e. print(a) rather than print(app), you'll see the items being added.
list.append() is a mutating method that returns None. In other words it changes the list, but doesn't return the list. Doing app = a.append(100) makes app refer to the result of None.
Change
app = a.append(100)
to
a.append(100)
app = a # these now reference the same mutated list
If you don't need two names for the same list drop the app = a.
If, on the other hand, you want a to reference the original list and app to reference a modified list then you would do
app = a + [100]

loop through a list with a function and store as variable

I have a list of variables I need to run though a function to produce a json table. I want to loop through this list (list_db) and create a new variable to look through them manually in spyder. I am having trouble creating those new variables from the for loop. I thought i could use the name of the items in list as the new variable name, but i cant get it to work. Here is what I have:
for i in list_db:
p = str(i)
p = getDF(i) #function to run
What am I missing? What is the more standard way of doing this i cant think of?
It seems variable names don't really act how you are expecting. When you do p = str(i), you are assigning to the variable p. And then your next line, p = getDF(i) overwrites the value of p. It does not write to a variable whose name is str(i) like you are expecting.
If you want to store values into named slots, you can use a dictionary:
p = {}
for i in list_db:
p[i] = getDF(i)

Creating a function that creates two lists in Python 3

I am trying to create a function, getStocks, that gets from the user two lists, one containing the list of stock names and the second containing the list of stock prices. This should be done in a loop such that it keeps on getting a stock name and price until the user enters the string 'done' as a stock name. The function should return both lists. My main issues are figuring out what my parameters are, how to continuously take in the name and price, and what type of loop I should be using. I am very new to programming so any help would be appreciated. I believe I'm close but I am unsure where my errors are.
def getStocks(name,price):
stockNames = []
stockPrices = []
i = 0
name = str(input("What is the name of the stock?"))
price = int(input("what is the price of that stock?"))
while i < len(stockNames):
stockNames.append(name)
stockPrices.append(price)
i += 1
else:
if name = done
return stockNames
return stockPrices
Your question is a bit unclear but some things off the bat, you cant have two return lines, once you hit the first, it leaves the function. Instead you'do write something like
return (stockNames, stockPrices)
Secondly while loops dont have an else, so you'd actually set up your while loop, then setup an if statement at the beginning to check if the string is 'done', then act accordingly. Break will get you out of your last while loop, even though it looks like it's associated with the if. So something like this:
while i < len(stockNames):
if name.upper() == 'DONE':
break
else:
stockNames.append(name)
stockPrices.append(price)
i += 1
Also you have to use == (comparison) instead of = (assignment) when you check your name = done. And dont forget done is a string, so it needs to be in quotations, and I used .upper() to make the input all caps to cover if its lower case or uppercase.
If you can clear up your question a little bit, I can update this answer to include everything put together. I'm not quite understanding why you want to input a list and then also take user input, unless you're appending to that list, at which point you'd want to put the whole thing in a while loop maybe.
Update:
Based on your comment, you could do something like this and enclose the whole thing in a while loop. This takes the incoming two lists (assuming you made a master list somewhere) and sends them both into the getStocks function, where someone can keep appending to the pre-existing list, and then when they type done or DONE or DoNe (doesn't matter since you use .upper() to make the input capitalized) you break out of your while loop and return the updated lists:
def getStocks(name, price):
stockNames = name
stockPrices = price
while 1:
inputName = str(input("What is the name of the stock?"))
inputPrice = int(input("what is the price of that stock?"))
if name.upper() != 'DONE':
stockNames.append(inputName)
stockPrices.append(inputPrice)
else:
break
return (stockNames, stockPrices)
But really, depending on the rest of the structure, you might want to make a dictionary instead of having 2 separate lists, that way everything stays in key:value pairs, so instead of having to check index 0 on both and hoping they didn't get shifted by some rogue function, you'd have the key:value pair of "stock_x":48 always together.

Resources