# Vanity plates Problem

The following code is my code for the vanity plates problem in cs50 introduction to python course. My issue is on the "Punctuation Function". When I enter an input with a punctuation, instead of returning "valid" or "invalid", it returns this attribute error:

``````Traceback (most recent call last):
File "plate.py", line 55, in <module>
main()
File "plate.py", line 6, in main
if is_valid(plate):
File "plate.py", line 13, in is_valid
if number(s) and length(s) and letter(s) and punctuation(s)==True:
File "plate.py", line 44, in number
for j in range(n.start()):
AttributeError: 'NoneType' object has no attribute 'start'
``````

Here is the code:

``````import re

def main():
plate = input("Plate: ")
if is_valid(plate):
print("Valid")
else:
print("Invalid")

def is_valid(s):
if number(s) and length(s) and letter(s) and punctuation(s)==True:
return True

def letter(s):
if s[0:2].isalpha():
return True
else:
return False

def length(s):
if 2 <= len(s) <= 6:
return True
else:
return False

def punctuation(s):
for i in s:
if not(i.isalpha() or i.isdigit()):
return False
return True

def number(s):
if s.isalpha():
return True
else:
n = re.search(r"\d+\$", s)
for m in s:
for j in range(n.start()):
if m.isdigit():
return False
else:
return True
if n.group(0) != 0 and n:
return True
else:
return False

main()
``````

## 1 Answer

TLDR
In summary your `punctuation` check should be carried out before the `number` check in `isvalid` and your `number` check is wrong aside from perhaps the `s.isalpha()` check.

Details
The problems.

1. You should do the punctuation check before you do the number check this would avoid the problem entirely.
2. In your `number` function if you give it input with punctuation and no digits what happens? In short, if there are no digits but punctuation what is `n`? remember if there is no match for `search` it returns `None`. And that's what is happening here, it is returning `None`. `None` doesn't have a `start` method. So you need to check that there is a match before going into that loop OR adjust the earlier pre-regex checks such that its guaranteed that you will have a match.

But frankly if you are going to use a regex there is no need for your loop at all. You can do all of the work from a properly formed regular expression to make sure that the input contains: only letters and numbers, starts with at least two letters, has no letters after numbers, and doesnt have a leading '0'.

1. Your loop also makes no sense at all. Why are you looping over meaningless `j` inside loop `for m in s:`?. You are just going to check each character of the string multiple times and inevitably find a digit and return false. Which is wrong.

2. The additional check `n.group(0) != 0 and n` is broken for several reasons. if `not n` then `n.group(0)` will throw an exception so at minimum invert the conditions to be `n and n.group(0) != 0`. Even this is silly as you will have thrown an exception on `n.start` if `n` is `None`. But assuming `n` was valid, you would have returned false above as I pointed out in flaw 2; but lets say you didn't. `n.group(0)` is your whole match. Which means it will be not equal to zero if any digit is non zero, but that doesnt mean the first digit isn't zero so you will return true on bad results, and potentially because of short comings elsewhere miss a number in the middle...

Figure out what you are trying to accomplish with each stage, and then set out and do it. Test just this function with sample input by calling it directly instead of calling `main` for example, add printouts to help you see what the code is doing, and look at the documentation for regular expressions if you are going to use them.

Good luck