daasca
daasca

Reputation: 31

string check function if else assert

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

Answers (2)

Beau
Beau

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

Chris
Chris

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

Related Questions