Python error cannot delete function call - python-3.x

In python I tried calling a function in a function - when I finished it says "error cannot delete function call". Why is this happening? Inside the nested function there is a delete used, but that is for a different variable! I tried a few things like printing the function instead but got the same answer.
Here is the code which isn't working:
def BracketStart():
Round2Normal=[]
Round1Loser=[]
if len(List) % 2 == 0:
print("The Current Match Is %s VS %s" %(min(List),max(List)))
starting=input("Start Match? --> ")
if starting=="Yes":
Winner1=input("Who Won? --> ")
if Winner1==min(List):
Round2Normal.append(min(List))
Round1Loser.append(max(List))
del min(List)
del max(List)

min(List) is a function call -- so, yes, you are trying to delete a function call. Perhaps
List.remove(min(List))
is the sort of thing you want to do (though calling a list "List" isn't a good choice and removing elements from a list is a relatively expensive operation).

Related

why does my depth first search continue to work even after finding the target?

I am building a depth first search function which is used on an undirected adjacency list. This function is meant to put all paths that successfully find the target node into the viable functions list and the non-viable paths into culdesac.
adjacencylist={1:[2,3],2:[1,4],3:[1,5],4:[2],5:[3]}
visited=[]
culdesacs=[]
viablepaths=[]
def dfs(graph,node,target,path,output):
if node in visited:
return
visited.append(node)
print(path)
if node==target:
output.append(path)
viablepaths.append(output)
return print('hello')
for nx in graph[node]:
dfs(graph,nx,5,path+[nx],output)
for element in path:
if element not in culdesacs:
culdesacs.append(element)
print(path)
print(culdesacs)
return print('oops')
dfs(adjacencylist,1,5,[1],[])
What I don't understand is why my function continues to work even after successfully hitting the target and even triggering the base case of my recursive program. For example in the function call dfs(adjacencylist,1,5,[1],[]), my starting node is 1 and my target node is 5. My function successfully found the path [1,3,5] and returned "hello". But then it continues to print oops and printing the paths [1,3] and [1].
Ideally, once it found the path[1,3,5], i would just like it to end the function altogether
How can I fix this
The problem is the following: When you're in
for nx in graph[node]:
dfs(graph,nx,5,path+[nx],output)
you start the recursive call that finds the target.
However, you do not return e.g. true in
if node==target:
output.append(path)
viablepaths.append(output)
return print('hello')
an do not check the return value.
I would recommend reading up on the beahvior of the call stack. Just because you end the recursive call that finds the value, the others are not cancelled

Is not using return value in Python bad practice/dangerous?

I have a function that only sometimes returns values. Below a simplified example.
def return_something(bool):
if bool:
return "Something"
else:
print("Hello ")
I figured that I could also rewrite the function as such:
def return_something():
print("Hello ")
return "Something"
As I only sometimes need the return value and when I need it the rest of the function may execute normally. Now I would call the function in two ways:
return_something()
string = return_something()
My question: When using the second design I don't use the returned value in the first function call. Is this considered bad practice and or dangerous?

Write a recursive function to list all paths of parts.txt

Write a function list_files_recursive that returns a list of the paths of all the parts.txt files without using the os module's walk generator. Instead, the function should use recursion. The input will be a directory name.
Here is the code I have so far and I think it's basically right, but what's happening is that the output is not one whole list?
def list_files_recursive(top_dir):
rec_list_files = []
list_dir = os.listdir(top_dir)
for item in list_dir:
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
list_files_recursive(item_path)
else:
if os.path.basename(item_path) == 'parts.txt':
rec_list_files.append(os.path.join(item_path))
print(rec_list_files)
return rec_list_files
This is part of the output I'm getting (from the print statement):
['CarItems/Honda/Accord/1996/parts.txt']
[]
['CarItems/Honda/Odyssey/2000/parts.txt']
['CarItems/Honda/Odyssey/2002/parts.txt']
[]
So the problem is that it's not one list and that there's empty lists in there. I don't quite know why this isn't not working and have tried everything to work through it. Any help is much appreciated on this!
This is very close, but the issue is that list_files_recursive's child calls don't pass results back to the parent. One way to do this is to concatenate all of the lists together from each child call, or to pass a reference to a single list all the way through the call chain.
Note that in rec_list_files.append(os.path.join(item_path)), there's no point in os.path.join with only a single parameter. print(rec_list_files) should be omitted as a side effect that makes the output confusing to interpret--only print in the caller. Additionally,
else:
if ... :
can be more clearly written here as elif: since they're logically equivalent. It's always a good idea to reduce nesting of conditionals whenever possible.
Here's the approach that works by extending the parent list:
import os
def list_files_recursive(top_dir):
files = []
for item in os.listdir(top_dir):
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
files.extend(list_files_recursive(item_path))
# ^^^^^^ add child results to parent
elif os.path.basename(item_path) == "parts.txt":
files.append(item_path)
return files
if __name__ == "__main__":
print(list_files_recursive("foo"))
Or by passing a result list through the call tree:
import os
def list_files_recursive(top_dir, files=[]):
for item in os.listdir(top_dir):
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
list_files_recursive(item_path, files)
# ^^^^^ pass our result list recursively
elif os.path.basename(item_path) == "parts.txt":
files.append(item_path)
return files
if __name__ == "__main__":
print(list_files_recursive("foo"))
A major problem with these functions are that they only work for finding files named precisely parts.txt since that string literal was hard coded. That makes it pretty much useless for anything but the immediate purpose. We should add a parameter for allowing the caller to specify the target file they want to search for, making the function general-purpose.
Another problem is that the function doesn't do what its name claims: list_files_recursive should really be called find_file_recursive, or, due to the hardcoded string, find_parts_txt_recursive.
Beyond that, the function is a strong candidate for turning into a generator function, which is a common Python idiom for traversal, particularly for situations where the subdirectories may contain huge amounts of data that would be expensive to keep in memory all at once. Generators also allow the flexibility of using the function to cancel the search after the first match, further enhancing its (re)usability.
The yield keyword also makes the function code itself very clean--we can avoid the problem of keeping a result data structure entirely and just fire off result items on demand.
Here's how I'd write it:
import os
def find_file_recursive(top_dir, target):
for item in os.listdir(top_dir):
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
yield from find_file_recursive(item_path, target)
elif os.path.basename(item_path) == target:
yield item_path
if __name__ == "__main__":
print(list(find_file_recursive("foo", "parts.txt")))

I am having trouble understanding the flow of programming

I am new to programming and one of the problems I have run across is structuring. I am learning Python (3) and am practicing by making a few practical programs. An issue I am running in to is how to get the right flow to the program. I find that as I write a function, I realize that I need it to lead to another function, so I end up calling the next function at the end of the function I'm writing. Then I realize that Python will read the code line-by-line, so I have to have the function I will be calling above the one I am actively writing. The effect is that I end up writing the program in reverse. For example:
#Replaces letters in chosen word with X's
def display_word():
selected_word = list(selected_word)
for x in selected_word:
x = "X"
print (x)
#Function that will display the welcome message when program launches
def start_screen():
user_input = input("Hello and welcome to Hang Man! If you would like to
start a game, please enter 'YES' now!")
user_input = user_input.upper()
if user_input == "YES":
display_word()
else:
print ("You're no fun!")
start_screen()
This is a little tid-bit that I have written in a hang-man program I am practicing with. I started out writing the start_screen function, then realized that I will need to call the display_word function within the start_screen function, but to do that, I will have to define the function before it is called, so I have to write the display_word function above the start_screen function, which effectively has me moving in reverse. My question is whether this is the way things go or if there is a better way to do things. It seems like writing the code in reverse is inefficient, but I am unsure if that is just my inexperience talking.
All functions in Python must be defined before they are used. That does not mean that the function has to be listed above the one it is called from.
The functions can be defined in any order. You just have to make sure the executable portions that start your program, like start_screen(), are called below where the function is defined.
In the case of your hangman program, you are perfectly safe to switch the order of the two functions.
In general, if you have all of your executable code following all of your function definitions, you are good to go to keep them in any order you choose!
Example:
This is perfectly ok. You can even switch them!
def fn1():
print('I am function 1')
fn2()
def fn2():
print ('I am function 2')
fn1()
This is bad!
fn1() #not defined yet!
def fn1():
print('I am function 1')
def fn2():
print ('I am function 2')
This is also bad!
def fn1():
print('I am function 1')
fn2() #not defined yet!
fn1()
def fn2():
print ('I am function 2')

return outside function, I don't believe it's indentation (return must be inside a function! can not test with statements)

Update (return must be inside a function! can not test with statements)
Keep getting
File "python", line 49
SyntaxError: 'return' outside function
bank=100
while True:
print('How much would you like to bet?')
bet=input()
bet=int(bet)
if bet not in range(1,bank+1):
print('please enter an amount you have!')
else:
return bet
Not exactly sure what is going on wrong and sorry for poor formatting but doing my best.
Update:
A run of it using repl.it
and the code itself
https://repl.it/Hl0p/0
You need to define a function to return values. Only a function can return values. Your code is a collection of statements and not a function. See how to write function over here.
https://docs.python.org/3/tutorial/controlflow.html#defining-functions

Resources