Why doesn't the try/except catch the NameError? - try-catch

def grades(score):
try:
if score >= .9:
return 'A'
elif score >= .8:
return 'B'
elif score >= .7:
return 'C'
elif score >= .6:
return 'D'
elif score <= .59:
return 'F'
else:
return 'Bad Score'
except NameError:
print('bad score')
x = grades(perfect)
print(x)

the error/exception is happening at x = grades(perfect) and not within your function grades, where you have your try/except block. The compiler won't allow your undefined variable (perfect) to be used as an argument.
Although it doesn't make a lot of sense, try the following:
try:
x = grades(perfect)
except NameError:
print('bad score')
For the function grades to make sense in regards of try/catch, you would always pass a defined variable as an argument and then cast the variable as a float (for this specific case). If the variable is a string, then you can catch a ValueError Exception. If the variable is = None, then catch a TypeError exception:
def grades(score):
try:
_score = float(score)
if _score >= .9: return 'A'
elif _score >= .8: return 'B'
elif _score >= .7: return 'C'
elif _score >= .6: return 'D'
elif _score <= .59: return 'F'
else: return 'Bad Score'
except ValueError: print('bad score')
except TypeError: print('bad score')
x = grades('perfect')
print(x)
or
perfect = None
x = grades(perfect)
print(x)

Related

I'm importing a file then trying to append, and populate, another array. I am trying to add a grade based on a mark. Typical high school example

I get the following error and don't know how to resolve it:
if marks >= 70:
TypeError: '>=' not supported between instances of 'list' and 'int'
MY CODE:
import csv, array
filename = 'students.csv'
name = []
marks = []
grade = []
v = ""
with open(filename) as f:
reader = csv.reader(f)
for row in reader:
name.append(row[0])
marks.append(row[1])
if marks >= 70:
v = "A"
grade.append(v)
elif marks >= 60:
v = "B"
grade.append(v)
elif marks >= 50:
v = "C"
grade.append(v)
else:
v = "D"
grade.append(v)
print(name)
print(marks)
print(grade)
I have tried setting marks to:
marks = [0] * 20, along with setting the other arrays to store 20 values.

Discord.py IF statement not passing?

I feel like this is an easy fix but I can't figure out why I'm getting this response.
I set each if statement to have a unique error message so I can see where the error is.
Every time I run $setbirthday 05/03 in my server I get the "Invalid month specified!" while the first index of my argument (0) would seemingly pass this.
Here is the code:
class BirthdayCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.command(pass_context=true)
async def setbirthday(self, ctx, args):
user = ctx.author
role = discord.utils.get(ctx.guild.roles, name="Creator")
if role in user.roles:
if args != '':
# If it's an actual month (index 0)
if args[0] != 0 or args[0] != 1:
await ctx.send("Invalid month specified!")
else:
# If it's an actual month (index 1)
if args[1] < 0:
await ctx.send("That's not a valid month!")
elif args[1] <= 9:
# If they separated month/day using "/"
if args[2] != "/":
await ctx.send("You have to specify your birthday like `MM/DD`!")
else:
# If it's an actual day (index 0)
if args[3] > 3:
await ctx.send("Invalid day specified!")
elif args[3] < 0:
await ctx.send("That isn't a day!")
else:
# If it's an actual day (index 1)
if args[4] < 0:
await ctx.send("Incorrect day!")
else:
# Make sure there's no extra numbers
if args[5] != '':
await ctx.send("Make sure it's just `MM/DD`!")
else:
birthday = args[0] + '' + args[1] + '' + "/" + args[3] + '' + args[4]
await ctx.send("Your birthday has been registered as: " + "`" + str(birthday) + "`" + "!")
else:
await ctx.send("Error!")
else:
await ctx.send("Set your birthday by doing `$setbirthday MM/DD`")
else:
await ctx.send("You don't have the required role to set your birthday!")
There are two main problems in your code :
You should use guard clauses instead of nesting if statements, it'll make your code easier to read and understand
You can use string.split() instead of having to comment what each index corresponds to, it also simplifies your conditions.
You then obtain this code:
#commands.command()
async def setbirthday(self, ctx, arg):
user = ctx.author
role = discord.utils.get(ctx.guild.roles, name="Creator")
if role not in user.roles:
return await ctx.send("You don't have the required role to set your birthday!")
if len(arg.split('/')) != 2:
return await ctx.send("You have to specify your birthday like `MM/DD`!")
month, day = arg.split("/")
if not month.isdigit() or not 1 <= int(month) <= 12:
return await ctx.send("Invalid month specified!")
if not day.isdigit() or not 1 <= int(day) <= 31:
return await ctx.send("Invalid day specified!")
await ctx.send(f"Your birthday has been registered as: {month}/{day}!")
Few things.
Problem #1: It seems that args[0] here would be a string, namely args[0] = '05/03'. The args are split by spaces (args = the arguments passed by the discord user excluding $setbirthday, and split by space). In order to extract the first character, you would need to do args[0][0]. Which would lead us to the next problem.
Problem #2: The if args[0] != 0 or args[0] != 1: is circular in essence. The way that the or operator works is that it checks if a is true OR if b is true, then proceed into the if statement. These conditions are independent of one another. Suppose that the input is the integer (number) 1. Then before your if statement can even get to or args[0] != 1, it has already triggered if args[0] != 0. After all, 0 != 1 . The correct operator here is and.
Problem #3: As I mentioned in #1, args[0] is a string and args[0][0] is a character. Your if statement is, in essence, checking if: '0' != 0. they are indeed not the same, so the if statement would still activate. You can either convert the character in args[0][0] to an integer (if int(args[0][0]) != 0) or you can compare args[0][0] to the character '0': (if args[0][0] != '0').
To sum all of that up, try this instead:
#String/Character Comparison
if (args[0][0] != '0') and (args[0][0] != '1'):
#Int Comparison
if (int(args[0][0]) != 0) and (int(args[0][0]) != 1):

Ruby Count Smiley Face - Exit Code = 1

The count smiley face question on Codewars, my codes passed all the tests, but an "Exit Code = 1" error message keeps popping up, what does that mean? What went wrong?
countSmileys([':)', ';(', ';}', ':-D']); // should return 2;
countSmileys([';D', ':-(', ':-)', ';~)']); // should return 3;
countSmileys([';]', ':[', ';*', ':$', ';-D']); // should return 1;
def count_smileys(arr)
first = ";:"
second = "-~"
third = ")D"
arr.select{|x|
third.include?(x[1]) or (second.include?(x[1]) && third.include?(x[2].to_s))
}.count
end
EDIT:
The error message is as below:
main.rb:8:in `include?': no implicit conversion of nil into String (TypeError)
from main.rb:8:in `block in count_smileys'
from main.rb:7:in `select'
from main.rb:7:in `count_smileys'
from main.rb:16:in `block in <main>'
from /runner/frameworks/ruby/cw-2.rb:55:in `block in describe'
from /runner/frameworks/ruby/cw-2.rb:46:in `measure'
from /runner/frameworks/ruby/cw-2.rb:51:in `describe'
from main.rb:11:in `<main>'
As the message describes, there's no implicit conversion of nil to string. Explicit does exist though:
2.3.1 :001 > nil.to_s
=> ""
You could parse your array for nil first, and then put it through the select method.
def count_smileys(arr)
first = ";:"
second = "-~"
third = ")D"
# parse your array for nil values here
arr.map {|x| x.nil? ? "" : x }
arr.select{|x|
third.include?(x[1]) or (second.include?(x[1]) && third.include?(x[2].to_s))
}.count
end
I realized what the problem is - there is a test count_smileys([";", ")", ";*", ":$", "8-D"]) where x[1] and x[2] would not be valid for the first 2 items in the array, so I need to fix the array inside the select method:
def count_smileys(arr)
first = ";:"
second = "-~"
third = ")D"
arr.select{|x|
x[1] = " " if x[1] == nil
x[2] = "" if x[2] == nil
(first.include?(x[0]) && third.include?(x[1])) || (first.include?(x[0]) && second.include?(x[1]) && third.include?(x[2]))
}.count
end
Joseph Cho was correct in the sense that nils need to be converted, but we should do it in the iteration, and common items x[1] should be set to an empty string with a space to avoid being counted, while x[2] is uncommon enough that an empty string would work.

How to get the arclen between two curve points in Maya?

In Maya 2015, I can get the arclen of a curve using this command:
cmds.arclen('bezier1')
But now I want to get the arclen of two points in my curve. Is there anyway to get this?
Using the Maya API, you can use the MFnNurbsCurve::findLengthFromParam (Maya 2016+ only). If you need it between two points, then call this function with each parameters and subtract.
If you don't want to use the api, then the other option is create a duplicate of your original curve and use "detach" it at the needed points and then use the arclen command on that new curve to get your length. So that is another way.
Note that when detaching a curve, it appears to try to keep the curvature as close the original as possible, but this isn't exact so the length may not be the same compared to the original curve. Maybe rebuilding the curve to have more points may increase the accuracy if that is an important factor for you.
Using Maya's API is surely the best way to do it as #scottiedoo said, but here is a function I made when I didn't know API and which gives you the same results.
from maya import cmds
def computeCrvLength(crv, startParam = None, endParam = None):
'''
Compute the length of a curve between the two given UParameters. If the both
UParameters arguments are set to None (default), will compute the length of
the whole curve.
Arguments:
- crv = string; an existing nurbCurve
- startParam = 0 <= float <= 1 or None; default = None; point parameter
value, if not None, will compute the points only between the startPt and
EndPt values.
- endParam = 0 <= float <= 1 or None; default = None; point parameter
value, if not None, will compute the points only between the startPt and
EndPt values.
Returns:
- The length of the curve between the given UParameters
- The length of the curve from its start to the startParam
- The length of the curve from its start to the endParam
'''
###### Exceptions
if cmds.objExists(crv) == False:
cmds.error ('The curve "%s" does\'nt exists.' % crv)
if cmds.filterExpand (crv, sm = 9) == None:
cmds.error ('The object "%s" is not a nurbCurve.' % crv)
if startParam != None:
if (0 <= startParam <= 1) == False:
cmds.error ('The start point parameter value must be between 0 and 1.')
if endParam != None:
if (0 <= endParam <= 1) == False:
cmds.error ('The end point parameter value must be between 0 and 1.')
if (startParam == None and endParam != None) or (startParam != None and endParam == None):
cmds.error ('The start and end points parameters must be both None or ' +
'both have values.')
if startParam != None and endParam != None:
if endParam < startParam:
cmds.error ('The end point parameter value cannot be less or ' +
'equal to start point parameter value.')
###### Function
if startParam == None and endParam == None:
crvLength = cmds.arclen (crv, ch = False)
distCrvToStartParam = 0
distCrvToEndParam = crvLength
else:
tmpArclenDim = cmds.arcLengthDimension (cmds.listRelatives(crv, s = True)[0]
+ '.u[0]')
cmds.setAttr (cmds.listRelatives(tmpArclenDim, p = True)[0] +
'.uParamValue', startParam)
distCrvToStartParam = cmds.getAttr (tmpArclenDim + '.al')
cmds.setAttr (cmds.listRelatives(tmpArclenDim, p = True)[0] +
'.uParamValue', endParam)
distCrvToEndParam = cmds.getAttr (tmpArclenDim + '.al')
cmds.delete (tmpArclenDim)
crvLength = (distCrvToEndParam - distCrvToStartParam)
return crvLength, distCrvToStartParam, distCrvToEndParam

How do I get the elsif for #correct_tries to work properly?

My first hangman game from scratch is almost done with the real basic stuff. I just need a counter for when a player gets it right to work correctly. I haven't figured out a good way to do it without deleting everything and starting over.
the #correct_tries counts correctly then in the elsif compare the numerical value to the number of elements in the given word that were answered correctly.
It'll keep counting when it should have stopped when #correct_tries was compared to the number when .inspect happens on the array. But it keeps counting.
class Hangman
Profanity = ['cobol','snit','crap','court']
Adjective = ['foul','repugnant','swift','fast']
Noun = ['king','queen','prince','princess']
def self.start_game
print "Welcome to Hangman V1 by Clueless! Please select which category of words do you want to use: \n Profanity, Adjective, Noun "
#selection = gets.chomp.downcase
case
when #selection == 'profanity'
puts 'You have selected profanity! '
hangman_word_selection
when #selection == 'adjective'
puts 'You have selected Adjectives! '
hangman_word_selection
when #selection == 'noun'
puts 'You have selected nouns! '
hangman_word_selection
end
end
def self.hangman_word_selection
if #selection == 'profanity'
hangman_word = Profanity.sample
hangman_word_setup(hangman_word)
#puts '_ ' * hangman_word.size
elsif #selection == 'adjective'
hangman_word = Adjective.sample
hangman_word_setup(hangman_word)
elsif
#selection == 'noun'
hangman_word = Noun.sample
hangman_word_setup(hangman_word)
end
end
def self.hangman_word_setup(hangman_word)
hangman_word_array = hangman_word.chars.to_a
#hangman_end = false
#while(#hangman_end == false)
#puts "*" * 40
#puts
#puts
puts 'You have five tries to get the word correct. If you can guess the whole word do so but you only have one try. Or just guess letter by letter.'
p hangman_word_array
#total_tries = 0
#correct_tries = 0
game_check = true
while game_check == true
first_try = gets.chomp.downcase
if(first_try == hangman_word_array[0] || first_try == hangman_word_array[1] || first_try == hangman_word_array[2] || first_try == hangman_word_array[3] || first_try == hangman_word_array[4])
puts 'Check'
#correct_tries += 1
p #correct_tries
#correct tries equal to the number of chars in the given word check it.
puts 'You have gotten it correct!'
elsif(first_try == hangman_word)
puts 'You have completed the word! Congratulations you win!'
hangman_win
break
elsif(first_try != hangman_word_array)
puts 'Wrong.'
#total_tries += 1
p #total_tries
#puts "*" * 40
elsif(#correct_tries == hangman_word_array.inspect)
puts 'done.'
break
end
end
end
def self.hangman_loss
puts ' +---+-
| |
| 0
| |\\
| /\\
-+----------'
puts 'You lose!'
end
def self.hangman_win
puts 'NEED HANGMAN VICTORY POSE HERE.'
end
start_game
end
The elsif condition
elsif(#correct_tries == hangman_word_array.inspect) will never be true. #correct_tries is a numerical value and hangman_word_array.inspect will return the array of words for hangman in a string format (e.g. hangman_word_array = ['a', 'b', 'c'] then hangman_word_array.inspect will be "[\"a\", \"b\", \"c\"]".

Resources