I'm trying to iterate through a list of NFL QBs (over 100) and add create a list of links that I will use later.
The links follow a standard format, however if there are multiple players with the same name (such as 'Josh Allen') the link format needs to change.
I've been trying to do this with different nested while/for loops with Try/Except with little to no success. This is what I have so far:
test = ['Josh Allen', 'Lamar Jackson', 'Derek Carr']
empty_list=[]
name_int = 0
for names in test:
try:
q_b_name = names.split()
link1=q_b_name[1][0].capitalize()
link2=q_b_name[1][0:4].capitalize()+q_b_name[0][0:2].capitalize()+f'0{name_int}'
q_b = pd.read_html(f'https://www.pro-football-reference.com/players/{link1}/{link2}/gamelog/')
q_b1 = q_b[0]
#filter_status is a function that only works with QB data
df = filter_stats(q_b1)
#triggers the try if the link wasn't a QB
df.head(5)
empty_list.append(f'https://www.pro-football-reference.com/players/{link1}/{link2}/gamelog/')
except:
#adds one to the variable to change the link to find the proper QB link
name_int += 1
The result only appends the final correct link. I need to append each correct link to the empty list.
Still a beginner in Python and trying to challenge myself with different projects. Thanks!
As stated, the try/except will work in that it will try the code under the try block. If at any point within that block it fails or raises and exception/error, it goes and executes the block of code under the except.
There are better ways to go about this problem (for example, I'd use BeautifulSoup to simply check the html for the "QB" position), but since you are a beginner, I think trying to learn this process will help you understand the loops.
So what this code does:
1 It formats your player name into the link format.
2 We initialize a while loop that will it will enter
3 It gets the table.
4a) It enters a function that checks if the table contains 'passing'
stats by looking at the column headers.
4b) If it finds 'passing' in the column, it will return a True statement to indicate it is a "QB" type of table (keep in mind sometimes there might be runningbacks or other positions who have passing stats, but we'll ignore that). If it returns True, the while loop will stop and go to the next name in your test list
4c) If it returns False, it'll increment your name_int and check the next one
5 To take care of a case where it never finds a QB table, the while loop will go to False if it tries 10 iterations
Code:
import pandas as pd
def check_stats(q_b1):
for col in q_b1.columns:
if 'passing' in col.lower():
return True
return False
test = ['Josh Allen', 'Lamar Jackson', 'Derek Carr']
empty_list=[]
for names in test:
name_int = 0
q_b_name = names.split()
link1=q_b_name[1][0].capitalize()
qbStatsInTable = False
while qbStatsInTable == False:
link2=q_b_name[1][0:4].capitalize()+q_b_name[0][0:2].capitalize()+f'0{name_int}'
url = f'https://www.pro-football-reference.com/players/{link1}/{link2}/gamelog/'
try:
q_b = pd.read_html(url, header=0)
q_b1 = q_b[0]
except Exception as e:
print(e)
break
#Check if "passing" in the table columns
qbStatsInTable = check_stats(q_b1)
if qbStatsInTable == True:
print(f'{names} - Found QB Stats in {link1}/{link2}/gamelog/')
empty_list.append(f'https://www.pro-football-reference.com/players/{link1}/{link2}/gamelog/')
else:
name_int += 1
if name_int == 10:
print(f'Did not find a link for {names}')
qbStatsInTable = False
Output:
print(empty_list)
['https://www.pro-football-reference.com/players/A/AlleJo02/gamelog/', 'https://www.pro-football-reference.com/players/J/JackLa00/gamelog/', 'https://www.pro-football-reference.com/players/C/CarrDe02/gamelog/']
I'm a little new to Python so I apologise in advance if this is a really simple question but I have been trying to wrap my mind around this problem for a while now.
Simply put, my code is to prompt the user if they have written down a couple of values correctly, If they have I want the loop to continue so the values can be saved to a database. If they have not I would like the code to loop back to the top of the while loop so they can re-enter the values.
For some reason when I enter 'no' It goes through the loop regardless, how may I fix this?
Here's the code below:
while True:
clear()
print("\nPlease input the required data.\n")
in_name = input('Name: ')
in_email = input('Email: ')
in_address = input('Address: ')
clear()
print("\nDoes this look correct?\n")
print("#--START--#\n")
print("Name: " + in_name)
print("Email: " + in_email)
print("Address " + in_address)
print("\n#---END---#\n")
validate == input(">>> ")
if validate == "no":
continue
elif validate == "yes":
print("/nAttempting to copy to the database...")
cursor.execute("""
INSERT INTO contacts(name, email, address)
VALUES (?,?,?)
""", (in_name, in_email, in_address))
conn.commit ()
print ( 'Data entered successfully.\n' )
break
(I should note that this write program is part of a larger program, the loop is nested within another loop that acts as the main menu, perhaps that may help.)
the keyword continue will take you back to the next iteration without finishing the current one, example.
for i in range(5):
if i == 2:
continue
print(i * 5)
This means that when i is 2 it wont print(i=2 * 5), instead it will go up to start the next loop where i=3. The output will be
0
5
15
20
If you use break, it will just completely stop and exit out of the iteration once it reaches this keyword.
I think you're looking for the keyword pass.
'while True:' will always be True, meaning the loop will go on forever. I believe that you'll need to break out of the loop for it to stop. Based on Jorge Alvarez's answer, even changing 'continue' to 'pass' will allow the loop to go forever.
If I understand correctly, you'll need to change the initial 'while True:' statement to test whether validate equals 'no' or 'yes'.
I have the script below, what I am finding that if my Try statement is satisfied, the whole iteration of the first loop will end and it will just go into the next loop iteration.
What I want to happen is it the, if statement, is satisfied, it then just back to the elif within the for loop that it sits within.
So essentially I want to go
For loop.
Then try if something works (I know some wont)
Then go back into a for loop (and all the subsequent loops will still work.
Ideally I would structure this as: for loop- try statement- for loop, but essentially I am asking the same question as when that happens to, the loop also breaks out.
Thaankyou, Sam
# LOOP OVER THE DICTIONARIES (CSV LINE DATA) AND PULL UP THE PARAMETER KEY TO MATCH
tester = []
updatefamilyname = IN[6]
typename_input01_value = IN[7]
typename_input02_value = IN[8]
for datarow_dict in Data_DictionaryList:
# Get matching value from data row dictionary
Matching_Value = str(datarow_dict[parameter_key_tomatch])
#test.append(parameter_key_tomatch)
#test.append(Matching_Value)
try:
Get_Matching_Value_LongIndex = Base_MatchingWalls_Dict[Matching_Value]
Split_Index = Get_Matching_Value_LongIndex.split(indexplacesplit)[1]
MatchedWall = Base_MatchingWalls[int(Split_Index)]
#test.append(MatchedWall)
#test.append("here2")
for para_key, para_value in datarow_dict.items():
#ResultOutput.append(para_key)
#ResultOutput.append(typename_input01_value)
#test.append(para_key)
#test.append(para_value)
# We then say if the paramter key is the same as the matching key, open the following
if para_key == parameter_key_tomatch:
#test.append("inside")
ResultOutput.append(para_key + " equal to " + para_value)
# Set New Family Type Name Value
#if para_key == typename_input01_key:
#typename_input01_value = para_value
#tester.append("inside link")
#elif para_key == typename_input02_key:
#typename_input02_value = para_value
#else:
#print ("go")
elif para_key != parameter_key_tomatch:
ResultOutput.append(para_key)
print ("not here")
#ResultOutput.append(para_key)
#TestParameter_ = testparavalue(MatchedWall, para_key, para_value)
#else:
#pass
# We then say, if its not the same, this is when we want to do some things, could be where we change the family name if we change the name of the name and number
else:
print ("ouside exception")
#ResultOutput.append("else why")
if updatefamilyname == "Yes":
ResultOutput.append("update name accepted")
print ("yes")
# THIS IS WHERE WE COULD PASS IN THE OTHER ONE TO MATCH TO FORM THE CHANGE IN FAMILY TYPE NAME
#typename_input01_value
#typename_input01_value
# This is where we bring in
# Anything where matching para does not have a corresponding wall type
except:
print ("here")
ResultOutput.append(Matching_Value)
I'm working on a HW assignment where I create a fake club with entry questions. If any of the questions are answered with "no", then the person isn't allowed to join.
I've tried going back to the og lessons about lists and loops, but I can't find what I'm trying to do on there.
Here's my code so far.
# Purpose: Create a fake club that has certain requirements, ask user to
# fill out the application, and print out their answers + results.
def main():
display = input('Hi! This is your application to The Aqua Project...')
display2 = input('Read the following questions and just type y or n')
# Weird list format...
user = [input('Are you at least 18 yrs old? '),
input('Can you work with other people? '),
input('Do you like animals? '),
input('Are you okay with getting dirty sometimes? ')]
# Here's the problem, I want to print 'sorry you cant join' once...
for i in range(4):
if user[i] != 'y':
print('Sorry, but you can\'t join our club')
justToShowInCMD = input('')
i += 1
else:
print('')
print('Congratulations, you have met all of our requirements!')
print('We will send an email soon to discuss when our team')
print('will meet up to help save some animals!')
print('In the meantime, visit our website at
TheAquaProject.com')
justToShowInCMD = input('')
main()
When you put a 'n' for some questions it says you can join, but for others it says you can't join. I don't know why sometimes it says you can when you placed a no in the interview, it shouldn't.
The usual ways to do this are a for loop with a break and an else clause:
for answer in user:
if answer != 'y':
print('Sorry')
break
else:
print('Congratulations')
Or the any() function:
if any(answer != 'y' for answer in user):
print('Sorry')
else:
print('Congratulations')
If one "no" means decline, you can add break to exit the loop after print decline info. Just like:
for i in range(4):
if user[i] != 'y':
print('Sorry, but you can\'t join our club')
justToShowInCMD = input('')
# i += 1 # <<<<<<<<<<<<<<<<<< this code may be not needed here
break # <<<<<<<<<<<<<<<<<< where to add break
else:
print('')
print('Congratulations, you have met all of our requirements!')
print('We will send an email soon to discuss when our team')
print('will meet up to help save some animals!')
print('In the meantime, visit our website at
TheAquaProject.com')
justToShowInCMD = input('')
or you can use a variable to indicate whether to decline, just like:
toDecline = False
for i in range(4):
if user[i] != 'y':
toDecline = True
if toDecline:
print('Sorry, but you can\'t join our club')
justToShowInCMD = input('')
else:
print('')
print('Congratulations, you have met all of our requirements!')
print('We will send an email soon to discuss when our team')
print('will meet up to help save some animals!')
print('In the meantime, visit our website at
TheAquaProject.com')
justToShowInCMD = input('')
There are a few ways to do this:
Use a flag variable and just output at the end. (Slightly inefficient if the first response is a no)
Use a flag variable and a while loop to exit as soon as the user responds with no. (Can be slightly confusing)
Use the builtin any method. (Can be confusing, not recommended)
flag = True
for i in range(4):
if user[i] != 'y':
flag = False # User has answered no to something, set the flag to false
if flag: # User has answered yes to everything
# <do your `yes` output>
else: # User has answered no to something
# <do your `no` output>
there are some small points in your code that need to be changed:
# Purpose: Create a fake club that has certain requirements, ask user to
# fill out the application, and print out their answers + results.
def main():
display = input('Hi! This is your application to The Aqua Project...')
display2 = input('Read the following questions and just type y or n')
# Weird list format...
user = [input('Are you at least 18 yrs old? '),
input('Can you work with other people? '),
input('Do you like animals? '),
input('Are you okay with getting dirty sometimes? ')]
# you define a variable inside function main
# and assign a list to it
# this variable will not be visible outside
# you should just return it
return user
# Here's the problem, I want to print 'sorry you cant join' once...
# call your function before you test the answer
# and assign the the result of the function to a
# variable you can use in your check
user= main()
# define a flag variabe to
# see if the answers are ok according your check
ok= True
for i in range(4):
if user[i].lower()[:1] != 'y':
# you could also use your original code
# in the check. The code above is an example
# how you could make sure the user can enter
# upper/lower case letters and also "yes"
# and "y" [:1] cuts off 1 character
# if the string is non-empty, otherwise it
# returns an empty string
print('Sorry, but you can\'t join our club')
justToShowInCMD = input('')
i += 1
# memorize that some question wasn't ok
ok= False
# I guess here you might want to exit the loop?
# so use a break, otherwise the other answers
# would be checked as well and the message
# output several times per user in some cases
break
if ok:
# this code here doesn't belong in the loop body
# I guess. It should be executed after all questions
# have been checked positive (which is only known
# after the loop has been executed)
# So here we are sure the answers were yes, because
# otherwise we would have set ok to False
print('')
print('Congratulations, you have met all of our requirements!')
print('We will send an email soon to discuss when our team')
print('will meet up to help save some animals!')
print('In the meantime, visit our website at TheAquaProject.com')
justToShowInCMD = input('')
# if you call your function here, you can't check
# the result of the input() calls because
# by the time you check it it has not been entered
I would suggest storing your questions in a list and using a for loop to ask them. Store the user's response to another list and check if there is any "n" in this list. See code below:
questions = ["Are you at least 18 yrs old?", "Can you work with other people?", "Do you like animals?", "Are you okay with getting dirty sometimes?"]
answers = list()
for question in questions:
user_answer = input(f"[y/n] {question}: ").lower()
answers.append(user_answer)
if "n" in answers:
print("Sorry, you can't join our club.")
else:
print("Congrats! You are in!!")
# you can print your desired messages as well.
Assuming you are iterating 4 times (using range(4))based on the length of user, what you can simple do is the following:
if 'n' or 'no' in user:
print('Sorry, but you can\'t join our club')
justToShowInCMD = input('')
else:
print('')
print('Congratulations, you have met all of our requirements!')
print('We will send an email soon to discuss when our team')
print('will meet up to help save some animals!')
print('In the meantime, visit our website at
TheAquaProject.com')
justToShowInCMD = input('')
You can modify the if condition to cater to other forms of negative answers like 'N' or 'No'. You don't need to iterate over user.
Comments on OP main():
A key point of programming, is code use efficiency.
Don't repeatedly call functions (e.g. input and print) when not necessary.
There are several ways your problem can be solved.
The other answers focus on your original user list, complete with repeatedly calling input
Once user executes, it essentially becomes a list of y and or n values, which you then unpack with a loop to check the values.
Another problem with the user list method, is it requires all of the questions to be answered, prior to disqualification. What if there were 40 questions? I'd be annoyed.
Incidentally, a list can be unpacked as follows: for value in user:. There is no need to address the list by index with python.
Updated main() implementation:
def print_list(values: list):
"""Print the values of a list"""
for value in values:
print(value)
def main():
"""Iterate through a questionnaire"""
# Variables at the top
intro = ['Hi! This is your application to The Aqua Project...',
'Read the following questions and just type y or n']
questions = ['Are you at least 18 yrs old? ',
'Can you work with other people? ',
'Do you like animals? ',
'Are you okay with getting dirty sometimes? ']
final = ['\nCongratulations, you have met all of our requirements!',
'We will send an email soon to discuss when our team',
'will meet up to help save some animals!',
'In the meantime, visit our website at www.TheAquaProject.com']
print_list(intro)
for i, question in enumerate(questions, start=1):
response = input(question)
if response == 'n': # can be replaced with != 'y'
print("Sorry, you can't join the club!")
break
if i == len(questions):
print_list(final)
Comments on updated main():
Instead of calling print a lot, store the text in a list and then call the print_list function to do the printing.
Keep custom functions separate
Custom functions should perform one function
values: list this is a type hint, which tells what data type the values parameter of print_list should be.
Annotations
"""""": use docstrings
Documenting Python Code: A Complete Guide
Double space between functions: How to Write Beautiful Python Code With PEP 8
main(): Defining Main Functions in Python
questions is obvious, it's just the questions from user, as a list without calling input
unpack questions with a for-loop and use the built-in function: enumerate.
There are many Built-in Functions
i goes with enumerate to count.
Other languages create a dummy variable, like count = 0, then use count+=1 to track loop iteration; this is considered not pythonic. Python uses enumerate, but only if you need a count for implementing something else.
if condition checks if response is n
If the if condition evaluates as True (e.g. when response = n, n == n is True), the user gets the sorry message, break, ends the loop, and the questionnaire is complete.
There are no nicities here, the function does not check to make certain a user enters y, it only checks for n. That wasn't in the scope of the question.
The start parameter of enumerate is set to 1. If all the questions are answered, i=4 and len(questions)=4 so i == len(questions) evaluates as True and the user gets the congratulations message.
len(questions) is used instead of 4, because it's a bad idea to hardcode in values like that, because then you have to remember you've done so. What if the number of questions changes? Then your if condition is broken.
Resources:
I'm not affiliated with RealPython, but they are a great source of incredibly in depth tutorials.
Lists and Tuples in Python
Basic Data Types in Python
I have a complex project and I will try to simplify one of the main problem of the project. So there is the simplification:
We can Imagine a while loop like this:
while(condition):
statement1
statement2
statement3
...
statementn
In this loop there n statements, and each statement can be whatever(function, loop, if statement,...) and there is a condition in the loop, this condition i want to check it BEFORE the while loop do it. Because if the condition is respect since the first statement I have to wait until the end of the while to check if the condition is respect... So there is my question is possible to check the condition BEFORE the loop without have a check-function between EACH statements of the whileloop ?
Because in fact, it's work... BUT the code isn't clear, I really think this way we pollute my code and i want to work more efficiently and with a beautiful code, so how can I solve my problem without this constraint ?
PS: I think about event listener like javascript but i found poor information about them on python, but if there is a tool which act like event listener it would be great !
It sounds like you want to clean up all your if-then-break statements into a single function that handles the "checking" of the value of a. For that purpose you could use exceptions:
import random
class ItIsFiveException(Exception): pass
def check(a):
if a == 5:
raise ItIsFiveException
try:
a = 0
while(a != 5):
a = random.randint(1,5); check(a)
a = random.randint(1,5); check(a)
a = random.randint(1,5); check(a)
a = random.randint(1,5); check(a)
except ItIsFiveException:
print("I saw a five!")
You just have to define your own python Exception as a class, and the raise it in your manually-defined check(a) function. Then you can wrap your entire while loop in a try-except block and catch your exception.
I am not sure if I understand you right, but this is what I'd do:
flag = False
while not flag:
for i in range(4):
a = random.randint(1, 5)
if a == 4:
flag = True
break
I don't know exactly what it happens with "a" but if if you can chain the conditions and will stop when the first one fails
while(checkRandom()):
...
def checkRandom(a):
return random.randint(1,5) == 5 and random.randint(1,5)....
If you can loop the generation of random values you can use
while(a!=5):
for item in range(1, 5):
a=random.randint(1,5)
if a==5:
break