Input Name with space with validation - python

I am using the .isalpha function to take an input of a name. It is working but whenever i put on space between name for example a full name John Doe It gives me error.
What ive Tried so far
while not name.isalpha():
print('Entered Name is invalid')
name = input('Please Enter Your Name Sir: ')
if name.isalpha() or name.isspace():
print('Hello Mr.' + name)
select_mmenu('main-menu.txt')
I've tried combining .isalpha and .isspace but it seems not to be working. Need the most simple way to solve this trick

isalpha tests that each member of the string is a letter. isspace tests that each member of the string is a whitespace character. Neither of those is what you want.
Instead you could do:
if all(lett.isalpha() or lett.isspace() for lett in name):
which will pass if every letter is EITHER a letter or a space. Alternatively you can match a regular expression:
import re # at the top of your module
if re.match(r"[\s\w]+$", name):
which is arguably cleaner, and certainly more powerful. The square brackets denote a character class, \s is all whitespaces and \w is all word character, the + means "matches 1 or more times," and the $ is the end of string. [\s\w]+$ then means "one or more characters that are either whitespace or word characters, and nothing afterwards.

It will certainly give you an error because the method isalpha() checks whether the string consists of alphabetic characters only. So if you put a space, the result will return false instead of true, and you will get an error.

Thankyou for the answers. I got it solved without using all() function. I just solved it with simplest basic Python loops
Thankyou Adam Smith because of your answer i got this idea to solve it through that method
con = False
while con!=True:
l=0
strs = input('Enter your Name: ')
for i in strs:
if i.isalpha() or i.isspace():
l += 1
if l == len(strs):
con = True
break
else:
print('Wrong Input')
if con==True:
print(strs)
In this code its basically counting the input lenght and alphabets and space lenght if it match it works. else the while loop continue.

Related

Print a string without any other characters except letters, and replace the space with an underscore

I need to print a string, using this rules:
The first letter should be capital and make all other letters are lowercase. Only the characters a-z A-Z are allowed in the name, any other letters have to be deleted(spaces and tabs are not allowed and use underscores are used instead) and string could not be longer then 80 characters.
It seems to me that it is possible to do it somehow like this:
name = "hello2 sjsjs- skskskSkD"
string = name[0].upper() + name[1:].lower()
lenght = len(string) - 1
answer = ""
for letter in string:
x = letter.isalpha()
if x == False:
answer = string.replace(letter,"")
........
return answer
I think it's better to use a for loop or isalpha () here, but I can't think of a better way to do it. Can someone tell me how to do this?
For one-to-one and one-to-None mappings of characters, you can use the .translate() method of strings. The string module provides lists (strings) of the various types of characters including one for all letters in upper and lowercase (string.ascii_letters) but you could also use your own constant string such as 'abcdef....xyzABC...XYZ'.
import string
def cleanLetters(S):
nonLetters = S.translate(str.maketrans('','',' '+string.ascii_letters))
return S.translate(str.maketrans(' ','_',nonLetters))
Output:
cleanLetters("hello2 sjsjs- skskskSkD")
'hello_sjsjs_skskskSkD'
One method to accomplish this is to use regular expressions (regex) via the built-in re library. This enables the capturing of only the valid characters, and ignoring the rest.
Then, using basic string tools for the replacement and capitalisation, then a slice at the end.
For example:
import re
name = 'hello2 sjsjs- skskskSkD'
trans = str.maketrans({' ': '_', '\t': '_'})
''.join(re.findall('[a-zA-Z\s\t]', name)).translate(trans).capitalize()[:80]
>>> 'Hello_sjsjs_skskskskd'
Strings are immutable, so every time you do string.replace() it needs to iterate over the entire string to find characters to replace, and a new string is created. Instead of doing this, you could simply iterate over the current string and create a new list of characters that are valid. When you're done iterating over the string, use str.join() to join them all.
answer_l = []
for letter in string:
if letter == " " or letter == "\t":
answer_l.append("_") # Replace spaces or tabs with _
elif letter.isalpha():
answer_l.append(letter) # Use alphabet characters as-is
# else do nothing
answer = "".join(answer_l)
With string = 'hello2 sjsjs- skskskSkD', we have answer = 'hello_sjsjs_skskskSkD';
Now you could also write this using a generator expression instead of creating the entire list and then joining it. First, we define a function that returns the letter or "_" for our first two conditions, and an empty string for the else condition
def translate(letter):
if letter == " " or letter == "\t":
return "_"
elif letter.isalpha():
return letter
else:
return ""
Then,
answer = "".join(
translate(letter) for letter in string
)
To enforce the 80-character limit, just take answer[:80]. Because of the way slices work in python, this won't throw an error even when the length of answer is less than 80.

Python Regex validation

I am brand new to Python.
I'm trying to ensure a username contains ONLY alpha characters (only a-z). I have the below code. If I type digits only (e.g. 7777) it correctly throws the error. If I type numbers and letters mix, but I START with a number, it also rejects. But if I start with a letter (a-z) and then have numbers in the string as well, it accepts it as correct. Why?
def register():
uf = open("user.txt","r")
un = re.compile(r'[a-z]')
up = re.compile(r'[a-zA-Z0-9()$%_/.]*$')
print("Register new user:\n")
new_user = input("Please enter a username:\n-->")
if len(new_user) > 10:
print("That username is too long. Max 10 characters please.\n")
register()
#elif not un.match(new_user):
elif not re.match('[a-z]',new_user):
print("That username is invalid. Only letters allowed, no numbers or special characters.\n")
register()
else:
print(f"Thanks {new_user}")
Why don't you use isalpha()?
string = '333'
print(string.isalpha()) # False
string = 'a33'
print(string.isalpha()) # False
string = 'aWWff'
print(string.isalpha()) # True
in your code, uf, un and up are unused variables.
the only point where you validate something is the line elif not re.match('[a-z]',new_user):, and you just check if there is at least one lowercase char.
To ensure that a variable contains only letters, use: elif not re.match('^[a-zA-Z]{1,10}$',new_user):
in the regex ^[a-zA-Z]{1,10}$ you find:
^ : looks for the start of the line
[a-zA-Z] : looks for chars between a and z and between A and Z
{1,10} : ensure that the char specified before (letter) is repeated between 1 and 10 times. As LhasaDad is suggesting in the comments, you may want to increase the minimum number of characters, e.g. to 4: {4,10}. We don't know what this username is for, but 1 char seems in any case too low.
$ : search for the end of the line
Since you were looking for a RegEx, I've produced and explained one, but Guy's answer is more pythonic.
IMPORTANT:
You're not asking for this, but you may encounter an error you're not expecting: since you're calling a function inside itself, you have a recursive function. If the user provides too many times (more than 1000) the wrong username, you'll receive a RecursionError
As the re.match docs say:
If zero or more characters at the beginning of string match the regular expression pattern, return a corresponding match object.
That's exactly what's happening in your case: a letter in the beginning of the string will satisfy the match. Try the expression [a-z]+$ which will make sure that the match expands till the end of the string.
You can check the length on the same go: [a-z]{1,10}$.

How to make sure the function turns what I write into a string

Here's the code:
abc = ['abcdefghijklmnopqrstuvwxyz', 'secondstring', 'thirdstring']
def findletter(letter, l1st, idx):
if letter in l1st[idx]:
print("found")
else:
print("not found")
findletter("i", abc, 0)
This works, however I have a few questions:
Why writing the letter the 'i' without quotation marks gives an error?
How do I make so it'd take letters without quotation marks?
Thanks.
A "letters without quotation marks" would be a variable.
If you set that variable to a string first, it will work without errors.
i = "something"
findletter(i, abc, 0)
Otherwise it's un undeclared variable, which is an error.
Writing i without quotations considers it as a variable which i has not been assigned to
For the second, str(abc) would work as str() converts what you have to a string
If you write "i" without the quotation marks, it will take it as a variable instead of a string.
If you do not want to hard-code what you to search, try this:
abc = ['abcdefghijklmnopqrstuvwxyz', 'secondstring', 'thirdstring']
def findletter(letter, l1st, idx):
if letter in l1st[idx]:
print("found")
else:
print("not found")
i = input("Enter the string to be searched: ")
findletter(i, abc, 0)
This will ask you what to search in the shell, every time you run the code and input() function always returns the value as a string.

Input validation (Python)

For input I need to have a string that contains both numbers and letters or only letters. Atm my code works with these conditions, but how can I add that input must not consist of punctuation marks?
nimi = input("...name: ")
while name.isalnum == True or name.isnumeric():
name = input("...name: ")
It's better to use regex.
if re.match(r'^(?!\d+$)[\da-zA-Z]+$', pass):
As stated above, using regex is better. But the below condition will work for you. Use string.punctuation to take count of all the punctuations.
import string
while(name.isalnum() or name.isalpha()) and not any(i in string.punctuation for i in name):

Remove members of a list in another list

I'm writing a program that checks if a word or sentence given by user input is a palindrome or not. This is the program so far:
def reverse(text):
a = text[::-1]
if a == text:
print "Yes, it's a palindrome."
else:
print "No, it's not a palindrome."
string = str(raw_input("Enter word here:")).lower()
reverse(string)
However, this code doesn't work for sentences. So I tried to do it like this:
import string
def reverse(text):
a = text[::-1]
if a == text:
print "Yes, it's a palindrome."
else:
print "No, it's not a palindrome."
notstring = str(raw_input("Enter word here:")).lower()
liststring = list(notstring)
forbiddencharacters = string.punctuation + string.whitespace
listcharacters = list(forbiddencharacters)
newlist = liststring - listcharacters
finalstring = "".join(newlist)
reverse(finalstring)
My goal is to put the punctuation and whitespace into a list and then subtracting those characters to the input of the user so that the program can tell if it's a palindrome even if the string has punctuation and/or whitespace. However, I don't know how I can subtract the elements in a list to the elements in another list. The way I did it, by creating another list that equals the user input minus the characters doesn't work (I tried it in my Xubuntu terminal emulator). Apart from that, when I run the program this error appears:
Traceback (most recent call last):
File "reverse.py", line 12, in <module>
forbiddencharacters = string.punctuation + string.whitespace
AttributeError: 'str' object has no attribute 'punctuation'
Ok so I have changed the variable name and I don't get that mistake above. Now I still don't know how to subtract the elements of the lists.
Since I'm a beginner programmer this might seem stupid to you. If that's the case, I'm sorry in advance. If anyone can solve one or both of the two problems I have, I'd be extremely grateful. Thanks in advance for your help. Sorry for bad english and long post :)
You should add some filtering along the way since palindromes have various syntax tricks (spaces, commas, etc.).
palindrome = "Rail at a liar"
def is_palindrome(text):
text = text.lower() #Avoid case issues
text = ''.join(ch for ch in text if ch.isalnum()) #Strips down everything but alphanumeric characters
return text == text[::-1]
if is_palindrome(palindrome):
print "Yes, it's a palindrome."
else:
print "No, it's not a palindrome."
You are on the right track, but you have used the identifier string for two different purposes.
Since you assigned to this variable name with the line:
string = str(raw_input("Enter word here:")).lower()
You can now no longer access the attributes string.punctuation and string.whitespace from the import string, because the name string is no longer bound to the module but to the user input instead.
A somewhat different approach to testing if a string is a palindrome
def palindrome(s):
s = s.lower()
ln=len(s)
for n in xrange(ln/2):
if s[n] != s[(ln-n)-1]:
return False
return True
print palindrome('Able was I ere I saw Elba')
FYI -- you'll need to tweak this to strip punctuation and white space if you like (left an an exercise to OP)
You can do that by splitting the phrase and storing it in a list. I am going to use your function (but there are more better pythonic ways to do that).
def reverse(textList1):
textList2 = textList1[::-1] #or we can use reversed(textList1)
if textList2 == text:
print "Yes, it's a palindrome."
else:
print "No, it's not a palindrome."
test1= "I am am I"
You should split the phrase and store it in a list:
test1List= test1.split(' ')
reverse(test1List)
Checking for palindrome is simple,
This works for both words and sentences.
import string
def ispalindrome(input_str):
input_str = list(input_str)
forbidden = list(string.punctuation + string.whitespace)
for forbidden_char in forbidden: # Remove all forbidden characters
while forbidden_char in input_str:
input_str.remove(forbidden_char)
return input_str == list(reversed(input_str)) # Checks if it is a palindrome
input_str = raw_input().lower() # Avoid case issues
print ispalindrome(input_str) # Get input

Categories

Resources