How to make this python regex work correctly - python

I need to validate a number with Python regex, but it is not working.
The code below is a library that is being used by another file. At this point, I am only trying to make the input be the only numbers between 13 and 19 digits. The range works just fine, but when I put a letter into the input, it prints it, instead of giving the "Invalid" string output:
"""
Credit card number validation and provider check
"""
import re
def card_range(cardNumber):
"""
Checks the credit card number length
"""
if len(cardNumber) < 13:
return "Invalid"
if len(cardNumber) > 19:
return "Invalid"
pattern = re.compile("[0-9]+")
if not pattern.match(cardNumber):
return "Invalid"
return cardNumber

You need boundary markers in your regex. But, I would just use a single pattern here:
def card_range(cardNumber):
return re.search(r'^[0-9]{13,19}$', cardNumber)
By the way, regular expressions for the major credit card providers are readily available, e.g. here.

Why not just check using the isnumeric method if the string appears to be a number? Seems like it'll be faster than the regex solution, since we just want to check for a number anyway.
def card_range(cardNumber):
"""
Checks the credit card number length
"""
if not cardNumber.isnumeric():
return 'Invalid! I need only NUMBERZ!'
if not 13 <= len(cardNumber) <= 19:
return "Invalid! The length check FAILED!"
return True
# Invalid! The length check FAILED!
print(card_range('1234567'))
# Invalid! I need only NUMBERZ!
print(card_range('a'))
# True
print(card_range('112233445566778899'))
# Invalid! I need only NUMBERZ!
print(card_range('1122334455x6778899'))

Related

Same input gives different output for a program

Novice programmer here. I am trying to write a program wherein it will take UIDs from user and validate them based on certain rules. The rules are:
It must contain at least 2 uppercase English alphabet characters.
It must contain at least 3 digits ( 0-9 ).
3.It should only contain alphanumeric characters (A -Z ,a -z & 0 -9 ).
No character should repeat.
There must be exactly characters in a valid UID.
I am putting in the code. Also apologies for this big code (I am a newbie)
# UID Validation
n=int(input()) #for iterations
uid=[]
# char=[]
valid=1
upper=0
numeric=0
# take input first of everycase
for x in range (0,n):
num=input()
uid.append(num)
# print (uid)
for i in uid:
# print (i)
# to count each word and number
count={}
for char in i:
count[char]=count.get(char,0)+1
for j in i:
if j.isupper():
upper=upper+1
elif j.isnumeric():
numeric=numeric+1
# print('numeric =', numeric)
# print('upper =', upper)
# Check conditions
while valid==1:
if len(i)!= 10:
valid= 0
# print('invalid for word count')
elif i.isalnum()== False: #alphanumeric
valid=0
# print('invalid for alnum')
elif upper<2: #minimum alphabet and numbers
valid=0
# print('invalid for min alphabet')
elif numeric<3:
valid=0
# print('invalid for min numeric')
else:
for k,v in count.items(): #no repitation
if v>1:
valid=0
# to check if given UID is valid or not
if valid==1:
print ('Valid')
elif valid==0:
print('Invalid')
valid=1
break
I have written the code but it seems that I am facing problem on one input only that is to check UID tag: 2TB1YVIGNM
It is an invalid tag. My program shows the same when is I run it alone or first in a batch of many. But, Lets say I run the program and input 2 tags, with "2TB1YVIGNM" being second one, it will show is as "Valid". Mind you, this is only happening in this particular tag
There are several other tags which run fine. Some of them are mentioned here:
77yS77UXtS
d72MJ4Rerf
OA778K96P2
2TB1YVIGNM "EXCEPT THIS TAG"
9JC86fM1L7
3w2F84OSw5
GOeGU49JDw
8428COZZ9C
WOPOX413H2
1h5dS6K3X8
Fq6FN44C6P
The output should be:
Invalid
Valid
Invalid
Invalid
Valid
Invalid
Invalid
Invalid
Invalid
Valid
Invalid
My output is this:
Invalid
Valid
Invalid
Valid
Valid
Invalid
Invalid
Invalid
Invalid
Valid
Invalid
To solve your problem you need to set upper and numeric back to 0 for each uid:
for i in uid:
upper = 0
numeric = 0
count={}
P.S: As for you newbie I would suggest you to read PEP 8 it will make your code more readable and prettier
P.S.S: There is no need to count manually how many times each character meet in string, such operation already implemented in Python look at the Counter for more details
And I agree with comment that for such type of tasks it is better to use regex
You could extract pieces of logic into functions and call them:
#It must contain at least 2 uppercase English alphabet characters.
def has_at_least_two_uppercase(potential_uid):
return sum([char.upper() == char for char in potential_uid])>= 2
#No character should repeat.
def has_unique_chars(potential_uid):
return len(set(potential_uid)) == len(potential_uid)
#There must be exactly characters in a valid UID.
def is_proper_length(potential_uid:str, proper_length:int = 10)-> bool:
return len(potential_uid) == proper_length
#It must contain at least 3 digits ( 0-9 ).
def has_three_digits(potential_uid):
return sum([char.isnumeric() for char in potential_uid])>=3
#It should only contain alphanumeric characters (A -Z ,a -z & 0 -9 )
# Defining a function for this may be an overkill to be honest
def is_alphanumeric(potential_uid):
return potential_uid.isalnum()
def is_valid_uid(potential_uid):
if has_at_least_two_uppercase(potential_uid) is False:
return False
if has_unique_chars(potential_uid) is False:
return False
if is_proper_length(potential_uid) is False:
return False
if has_three_digits(potential_uid) is False:
return False
if is_alphanumeric(potential_uid) is False:
return False
return True
Side notes:
use is to check for True/False
use True/False and not 1/0 for boolean conditions (like valid variable)
[OPTIONAL / homework]
use docstrings instead of comments
add add type hints (see is_proper_length as an example)
you can use all() and pass all the calls into it, but the ifs will short circuit from the function without checking all the conditions (all depends on a problem, like number of conditions, length of the UID, number of UIDs to be checked etc.) and you can play around with order of the checks e.g. if the length is not right there's no need to check the rest (but it's a pre-optimization in a way, which is discouraged in general)
parametrize your functions further if need be, define params for number of upper to check, numeric and so on

How to use raw_input with no input

I want to use raw_input() function in Python.
I want to receive a number from user about the size of the storage
i wrote this down :
number=raw_input()
if the user doesn't provide an input then number = 10 so
if number is None:
number = 10
when i print number, i get nothing i even tried:
if number==-1:
number=10
print"the storage size was set to:",number
The output was:
>
the storage size was set to -1
and not 10
So how should I solve this ?
If you don't care to distinguish between "no input" and "invalid input" (like a non-integer literal), set the default, then attempt to replace it with the user input.
number = 10
try:
number = int(raw_input())
except (EOFError, ValueError):
pass
ValueError will be raised on invalid inputs, including the empty string. EOFError is raised if the user does something like type Control-d in a terminal that interprets that as closing standard input.
First of all you have to convert the input (default for raw_input is a string) into an int using int() function. But be sure that you first check if user typed something. Otherwise you can't convert an empty string. For example:
num_input = raw_input()
if num_input:
number = int(num_input)
Then already the second part of your question should work:
if number == -1:
number = 10
print "the storage size was set to:", number
The second point is that an empty string is not equal to None. None is the only value of NoneType and "" is a string.
So you can compare the input with an empty string, but you can do better (an empty string is evaluated as False):
if not num_input:
number = 10
and to be even more efficient you can simply add an else statement to my first piece of code:
num_input = raw_input()
if num_input:
number = int(num_input)
else:
number = 10
compare number with empty string; not with None .
if number == '':
number = 10
In Python when the variable is empty then it's have inside empty '',
so if you want to check if your variable is unset you need to compare it to '' and not to None.
if number=='':
number=10
You should just compare number and empty.:
if number=="":
number==10

Why does this code not work for all inputs

I am trying to write python code that takes two strings as input and checks if all the characters of the second string are present in the first string. If so, then the output is the second string. If not, the output is the string "This does not work". I have tested this procedure for a variety of inputs, and it typically works, but not always. For example, if my two inputs are "helo" and "olhe", respectively, the output is "This does not work," whereas it should be "olhe" since all the characters in "olhe" are present in "helo."
Here is my code
def fix_machine(debris,product):
n = 1
while True:
first_element = product[0:n]
find_first_element = debris.find(first_element)
if first_element == product:
return product
break
n = n + 1
if find_first_element == -1:
return "This does not work"
break
So why does this not work?
You could do this as a more elegant solution, assuming that you strictly want all of the second string characters to be present in first.
def fix_machine(first, second):
for character in second:
if character not in first:
return False
return second
This returns correct input for your code. Not entirely sure what is wrong with your code as I have not stepped through.
EDIT: Albert has a much more elegant solution, reference his
As far as I understood you just want to compare two strings containing different characters.
For doing so, I would suggest converting both strings to a set which then provides (in contrast to a list) order-less comparison of its elements.
def check_string(first_str, second_str):
# convert strings to sets in order to compare characters
if set(first_string) == set(second_string):
return second_str
else:
return 'This does not work.'
first_string = 'helo'
second_string = 'olhe'
print(check_string(first_string, second_string))
# prints True
first_string = 'helo'
second_string = 'hello'
print(check_string(first_string, second_string))
# prints True
first_string = 'helo'
second_string = 'helofoo'
print(check_string(first_string, second_string))
# prints 'This does not work.'
I agree that you should step through that code with a debugger (maybe try PyCharm if you don't have an IDE set up yet) to see what went wrong. Would be hard to explain whats going wrong but I think it has something to do with first_element = product[0:n]. This will return increasingly larger segments of the string. i.e. 'ol' on the second run through.
Here's an alternative way of writing it
def fix_machine(debris, product):
all_present = all(letter in debris for letter in product)
return product if all_present else 'This does not work'

Testing Valid Input Python

So I have a finished program that accepts an input file with bank account information and parses it up and allows for a few different utilities.
One such utility is adding a transaction to the "database" (just a log file).
The program prompts the user to enter 'w' or 'd' and then an amount (float). This represents a deposit or withdrawal of X amount of money.
I was wondering how to go about making sure that the user entered either 'w' or 'd' AND a correct amount (number).
So, I decided that a while loop with the above condition would work, however I am having trouble getting it work 100%
I initially had:
while input1 is not ("w" or "d")
where input1 would be the first input (w or d) the user enters
However, I also want to check that a number exists.
I had the idea of casting the string input to a float, then checking that but I wouldn't know how to checking if that is right since casting and checking the type wouldn't tell me much.
How would I also check that the user entered in some sort of number.
So to reiterate, I would like the program to re-prompt for input if the user did not enter either:
A) A w or d
B) A number (int/float)
Thanks
the expression ("w" or "d") will always evaluate to "w". Generally, here you want an in:
while input1 not in ("w", "d"):
...
As far as handling the case where the input is a number, this is a job for a helper function:
def string_is_number(s):
try:
float(s)
return True
except ValueError:
return False
Now you can use that with the above to put the whole thing together:
while (not string_is_number(input1)) and (input1 not in ("w", "d")): ...
Which can actually be simplified a little more:
while not (string_is_number(input1) or (input1 in ("w", "d"))): ...
And now a completely different approach, You can actually use a recursive function for this sort of thing. Combine that with python's exception handling and we could probably put together a pretty elegant solution in just a few lines:
def prog_loop():
# prompt for user's input here:
input1 = raw_input("Enter a number, or 'w' or 'd':")
# See if we got a number
try:
number = float(input1)
except ValueError:
# Nope, wasn't a number. Check to see if it was in our
# whitelisted strings. If so, break early.
if input1 in ('w', 'd'):
return function_handle_w_d(input1)
else:
# Yes, we got a number. Use the number and exit early
return function_handle_number(number)
# haven't exited yet, so we didn't get a whitelisted string or a number
# I guess we need to try again...
return prog_loop()
This will work as long as your user doesn't enter bad input 1000 times.
Try this:
while True:
if input1 == 'w':
withdraw()
elif input1 == 'd':
deposite()
else:
continue()

get the list and input from one function and run them in different function

i have a programm that generate the list and then i ask them to tell me what they want to do from the menu and this is where my problem start i was able to get the input form the user to different function but when i try to use the if else condition it doesn't check, below are my code
def menu(x,l):
print (x)
if x == 1:
return make_table(l)
if x == 2:
y= input("enter a row (as a number) or a column (as an uppercase letter")
if y in [ "1",'2','3']:
print("Minmum is:",minimum(y,l))
if x== 3:
print ('bye')
def main():
bad_filename = True
l =[]
while bad_filename == True:
try:
filename = input("Enter the filename: ")
fp = open(filename, "r")
for f_line in fp:
f_str=f_line.strip()
f_str=f_str.split(',')
for unit_str in f_str:
unit=float(unit_str)
l.append(unit)
bad_filename = False
except IOError:
print("Error: The file was not found: ", filename)
#print(l)
condition=True
while condition==True:
print('1- open\n','2- maximum')
x=input("Enter the choice")
menu(x,l)
main()
from the bottom function i can get list and i can get the user input and i can get the data and move it in second function but it wont work after that.thank you
I think your problem is simple, and has nothing to do with how you're passing values between functions.
In main, you're reading a value from the user like this:
x=input("Enter the choice")
The input function:
… reads a line from input, converts it to a string (stripping a trailing newline), and returns that.
So, if the user types 1 at the prompt, you get back the string "1".
Now, you pass that value—perfectly correctly—to menu.
In menu, you then try to compare it to various numbers, like this:
if x == 1:
But this will never be true. A string, like "1", is never equal to a number, like 1. They're not even the same kind of value, much less the same value.
So, you need to do one of two things:
Convert the input to an number. For example, change menu(x,l) to menu(int(x), l). OR…
Write menu to expect strings. For example, change if x == 1: to if x == "1":.
You may be wondering why that print (x) didn't help you debug the problem.
print(x) prints out the end-user-friendly string representation of whatever you give it. That is, it automatically calls the str function for you. For debugging purposes, you often want to use repr instead of str, to get the programmer-friendly string representation instead of the end-user-friendly string representation.
For example, print(str("10")) will print out 10—just like print(str(10)), so you can't tell them apart. But print(repr("10")) will print out '10', unlike print(repr(10)), while prints 10, so you can tell them apart. repr can also help you spot things like strings with invisible characters in them, having special "node" objects from a parser instead of just strings, etc.

Categories