Reputation: 31
Beginner here. My code should be able to check that a given number is in the form xxx-xx-xxxx. The if statement is wrong somewhere I think. Any tips welcome thank you.
def checkit(a):
if a is (int[0:2]+"-"+ int[4:5] +"-"+int[7:8]):
print("True")
else:
print("False")
assert checkit(832-38-1847)
assert not checkit(832- 23- 1 847)
print("/n(Good job!)")
Error message:
Traceback (most recent call last):
File "nb5a.py", line 19, in <module>
assert checkit(832-38-1847)
File "nb5a.py", line 14, in checkit
if a is (int[1:3]+"-"+ int[5:6] +"-"+int[8:9]):
TypeError: 'type' object is not subscriptable
Upvotes: 2
Views: 9205
Reputation: 91
The error message is telling you that you are trying to subscript the type "int". Based on what I infer you are wanting to do, slice (subscript) you variable "a", and then verify that the slice is an integer (int) which, in it's simplest for could be something like int(a[0:2]) + "-" + int(a[4:5]) + "-" + int(a[7:8])
. However, this technique has some major flaws. If any of the slices can't be converted to an type "int", python will throw ValueError: invalid literal for int() with base 10: <whatever value threw the error>
. You could improve this a little using a "try" "except" block:
try:
int(a[0:2]) # etc...
except:
print("Not the correct format")
but this is pretty cumbersome, and should you ever need to evaluate something more complicated it can get really cumbersome and lot of lines of code to evaluate properly.
A more concise way to validate the expression would be to use a regular expression. Regular expressions are a very concise, and a consolidated way to check values, match format, and value type (int or string only).
Also, the argument value(s) your are trying to pass into your checkit function would be misinterpreted by python as a mathematical expression. You need to surround your argument values with single-quotes or double-quotes.
Here is one possible way to check your desired format and value type ((Note: this example is a little contrived in order to see the assert statement in action if the assertion fails)):
import re
def checkit(a):
pattern = r'^([0-9]{3})-{1}([0-9]{2})-{1}([0-9]{4})$'
match = re.fullmatch(pattern, a)
if match != None:
match = match.string
try:
assert a == match, "Fail"
print("True")
print("\n(Good job!)")
except:
assert a == match, "Fail"
print("False")
print("Not the correct format or values or both")
If you don't really need the assert statement, this could be an even shorter way of validating the values:
import re
def checkit(a):
pattern = r'^([0-9]{3})-{1}([0-9]{2})-{1}([0-9]{4})$'
match = re.fullmatch(pattern, a)
if match != None:
print("True")
print("\n(Good job!)")
else:
print("False")
print("Not the correct format or values or both")
To learn more, and get a better understanding about regular expressions, follow this link about regexp
This website might be helpful also PyRegex
By the way, to parse and validate the string as closely to the method you used in your example, you could do something like this:
def checkit(a):
try:
slicedVal = str(int(a[0:3])) + '-' + str(int(a[4:6])) + '-' + str(int(a[7:11]))
print(slicedVal)
# Caution!
# If you want to match exactly the number of digits in the last portion of xxx-xx-xxxx variable
# the slice or the assert statement will not catch this error or fail
# Slicing a string with a number greater than it's length will pass without errors
# e.g.
# >>> print('I will pass'[0:2000])
# I will pass
assert slicedVal == a, "FAIL"
print("True")
return slicedVal
except:
print("False")
success = '832-38-1847'
assert success == checkit(success), "This won't fail this assertion test"
# True
# Should technically fail if formatting match is required
doesNotFail = '832-38-184'
assert doesNotFail == checkit(doesNotFail), "This won't fail this assertion test"
# True
willFail = '832- 23- 1 847'
assert willFail == checkit(willFail), "This one will fail for sure"
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# AssertionError: This one will fail for sure
print("/n(Good job!)")
#
# (Good job!)
Upvotes: 2
Reputation: 1615
Try using a regular expression:
import re
def checkit(a):
return bool(re.match("^[0-9]{3}-[0-9]{2}-[0-9]{4}$", a))
checkit("832-38-1847")
#> True
checkit("832- 23- 1 847")
#> False
Created on 2018-09-23 by the reprexpy package
import reprexpy
print(reprexpy.SessionInfo())
#> Session info --------------------------------------------------------------------
#> Platform: Darwin-17.7.0-x86_64-i386-64bit (64-bit)
#> Python: 3.6
#> Date: 2018-09-23
#> Packages ------------------------------------------------------------------------
#> reprexpy==0.1.1
Upvotes: 0