Python3 mask-string - python

I am trying to solve an exercise in python3 and I can't get it to work.
I have this code:
def mask_string(string3):
"""Mask string"""
s = string3[-4:].rjust(len(string3), "#")
masking_string = ""
string3_length = len(s)
result = multiply_str(masking_string, string3_length) + s
return result
def multiply_str(string3, masking_string):
"""Mulitply string"""
new_multiply_str = string3 * int(masking_string)
return new_multiply_str
And I am running it like this:
elif choice == "10":
string3 = input("Enter a string that will replace all of the caracters with # exept the 4 last ones: ")
print(marvin.mask_string(string3))
masking_string = input("Enter number: ")
print(marvin.multiply_str(string3, masking_string))
And I get this error when I run it:
line 131, in multiply_str new_multiply_str = string3 * int(masking_string)
ValueError: invalid literal for int() with base 10: ''
Would really appreciate some help, and please dumb it down a lot when explaining because I am new to python and still do not understand a lot of how to do things.

line 131, in multiply_str new_multiply_str = string3 * int(masking_string)
ValueError: invalid literal for int() with base 10: ''
Therefore your masking_string was "" which is not a valid number (integer or not). You must have pressed enter without entering a number.
If you want to prevent this, wrap your input routine in a loop and only return when you have a number:
def get_int():
while True:
x = input("Number: ")
try:
return int(x)
except ValueError:
print(f"Invalid input {x}, try again...")

Related

how to print getValidInteger? python

I'm a beginner in the Python language. I have my getValidInteger function which is:
def getValidInteger():
isValid = False
#initialize strInput
strInput = ""
while (not isValid):
#get string input from the user
strInput = input('Enter an integer: ')
isValid = IsValidInteger(strInput)
if (not isValid):
print('Invalid integer was entered: try again')
#after exiting the loop return strInput cast to an int
return int(strInput)
However, I cannot call that function in the line code below. It shows Typererror: TypeError: getValidInteger() takes 0 positional arguments but 1 was given
setSizeSmall = um.getValidInteger('Enter a small size of each subset:')
I want the output to look like :
Enter a small size of each subset:
I dont know what is your IsValidInteger() function but it doesn't seem to take arguments.
Instead, you can use the isdigit() method like this
def getValidInteger():
isValid = False
#initialize strInput
strInput = ""
while (not isValid):
#get string input from the user
strInput = input('Enter an integer: ')
isValid = strInput.isdigit()
if (not isValid):
print('Invalid integer was entered: try again')
#after exiting the loop return strInput cast to an int
return int(strInput)

How to specify parameters for input

I want to only allow a user to input a string followed by an integer and separated using a comma and if they do not comply I would like to let them know that they have inputted incorrectly and to let them try again. I am having trouble finding a way to do this, I can make the input require a comma but I do not know how to specify a string and int on each side.
name_age = []
user_input = []
name_age2 = []
ages = []
while user_input != "":
try:
user_input = input("Type 'Name,Age': ")
name_age.append(user_input)
print(name_age)
if "," not in user_input:
raise ValueError
except ValueError:
print("Incorrect try again")
else:
name_age.remove("")
for item in name_age:
name_age2.append(item.split(','))
for pair in name_age2:
for val in pair:
if val.isdigit():
ages.append(int(val))
print(name_age2)
print(ages)
print("Names & Ages: ", name_age2)
print("Total of ages: ", sum(ages))
print("Average of ages: ", sum(ages) / len(ages))
print("Total number of names: ", len(name_age2))
print("End")
you can for example make a function to validate the user input, like this.
Here's an example, it's working, but you have to make some modifications.
name_age = []
user_input = []
name_age2 = []
ages = []
def validate(input: str) -> bool:
decomposed_string: str = input.split(',')
if decomposed_string[1].isdigit() and not decomposed_string[0].isdigit():
return True
return False
while user_input != "":
try:
user_input = input("Type 'Name,Age': ")
name_age.append(user_input) if validate(user_input) else print("Incorrect, try again")
print(name_age)
if "," not in user_input:
raise ValueError
except ValueError:
print("Incorrect try again")
else:
name_age.remove("")
for item in name_age:
name_age2.append(item.split(','))
for pair in name_age2:
for val in pair:
if val.isdigit():
ages.append(int(val))
print(name_age2)
print(ages)
print("Names & Ages: ", name_age2)
print("Total of ages: ", sum(ages))
print("Average of ages: ", sum(ages) / len(ages))
print("Total number of names: ", len(name_age2))
print("End")
Regex patterns suits very well for this kind of simple string parsing. Other solution in complex cases would be to go for some third party library PyParsing or Parsley.
With regex groups and especially named groups are very handy. Here's a simple example:
name_age_pattern = re.compile(r'(?P<name>\w+),(?P<age>\d+)')
def parse_name_age(string):
match = name_age_pattern.match(string)
if not match:
raise ValueError('input string didnt match pattern')
return match.group('name'), int(match.group('age'))
name, age = parse_name_age('Jack,23')
Then some extra hints. To make your code a little bit more pythonic you could use some classes. Here's a sample:
import re
from typing import NamedTuple
class Person(NamedTuple):
name: str
age: int
name_age_pattern = re.compile(r'(?P<name>\w+),(?P<age>\d+)')
#classmethod
def from_string(cls, string):
match = cls.name_age_pattern.match(string)
if not match:
raise ValueError('input string didnt match pattern')
return cls(match.group('name'), int(match.group('age')))
class People(list):
# Inheriting from a list should be made with caution. Overriding
# native functions could result unwanted side effects. We should
# be safe here since we don't do so.
#property
def names(self):
return ', '.join((person.name for person in self))
#property
def total_age(self):
return sum((person.age for person in self))
#property
def avg_age(self):
return self.total_age / len(self)
people = People()
while True:
input_str = input('Please give a name and age separated by a comma.')
if input_str == "":
break
try:
people.append(Person.from_string(input_str))
except ValueError as e:
print(e)
print(people.names)
print(f'sum of ages: {people.total_age}')
print(f'avg of ages: {people.avg_age}')
Here I have used a regex for your condition to validate the input:
import re
name_age = []
user_input = []
name_age2 = []
ages = []
while user_input != "":
try:
user_input = input("Type 'Name,Age': ")
name_age.append(user_input)
print(name_age)
if not re.search('^\w+(\s+\w+)*,\d+', user_input):
raise ValueError
except ValueError:
print("Incorrect try again")
else:
name_age.remove("")
for item in name_age:
name_age2.append(item.split(','))
for pair in name_age2:
for val in pair:
if val.isdigit():
ages.append(int(val))
print(name_age2)
print(ages)
print("Names & Ages: ", name_age2)
print("Total of ages: ", sum(ages))
print("Average of ages: ", sum(ages) / len(ages))
print("Total number of names: ", len(name_age2))
print("End")
So this regex would accept names with spaces example "anosha rehan, 12" but if you're looking for only one word names so use this regex '(\w+)*,\d+'
You can use regex to match the exact pattern you want from users input.
The regex defined below would match:
[a-zA-Z]+ - one or more alphabet (both lower and upper case)
, - literal comma character
\d{1,3} - a range between 1 to 3 digits. $ must end in digit
import re
# input_text_sample = 'john,24'
input_pattern = re.compile(r'[a-zA-Z]+,\d{1,3}$')
correct_input = None
while not correct_input:
user_input = input("Type 'Name,Age': ")
correct_input = input_pattern.match(user_input)
if not correct_input:
print("Incorrect try again")
else:
print(correct_input.string)

How can I fix EOF problem in the second script (below the dotted line)?

This program essentially encodes and decodes a message and code respectively. I only did the decoding part so far. However I keep getting an EOF error even though I made sure to end parentheses, checked my syntax and kept tampering with it. Unfortunately no luck. Anyone know why this error keeps popping up? I would greatly appreciate it. Also I copied both files that i'm using.
from LetterCodeLogic import LCL
def main():
print("Welcome to the LetterCode program")
choice = getChoice()
while choice !=0:
if choice == 1:
#Encode logic...
print()
elif choice == 2:
#Decode logic...
msg = input("Enter your numbers to decode (separate with commas): ")
#send msg to Decode function in LCL class (LetterCodeLogic.py file)
result = LCL.Decode(msg)
print("Your decoded message is: \n" + result)
else:
print("Unknown process...")
print()
choice = getChoice()
print("Thanks for using the Letter Code program")
def getChoice():
c = int(input("Choice? (1=Encode, 2=Decode, 0=Quit): "))
return c
if __name__ == "__main__":
main()
class LCL:
"""Encode/Decode Functions"""
#staticmethod
def Decode(msg):
#separate numbers from msg string (e.g., "1,2,3")
nums = msg.split(",") #produces list of separate items
result = ""
for x in nums:
try:
n = int(x.strip()) #remove leading/trailing spaces...
if n == 0:
c = " "
elif n < 0 or n > 26:
c = "?"
else:
#ASCII scheme has A=65, B=66, etc.
c = chr(n+64)
except ValueError:
c = "?"
result += c #same as: result = result + c
return result
#staticmethod
def Encode(msg):
the "#staticmethod" and "def Encode()" function was empty and that was the end of line parsing error. When I was coding this and ran it, it ran with no problems. So I removed it for the time being.

change (lack of) user input to default string value

This is probably a straight forward question but I don't have the Python fundamentals down yet (running before walking)
I want user inputs for the following (coordinate) variables:
source_x = input('enter blast x: ')
source_y = input('enter blast y: ')
source_z = input('enter blast z: ')
receiver_x = input('enter receiver x: ')
receiver_y = input('enter receiver y: ')
receiver_z = input('enter receiver z: ')
When the user input is Enter for the z coordinate (or any other), the following error arises:
source_z = float(source_z)
ValueError: could not convert string to float: ''
I understand the error, the Enter input was seen as a string, but is there a quick way to identify and convert the Enter input to (e.g.) a 0?
Just in case I want to undertake bulk imports and not stop my calculations further down the code.
kind regards
The solution is to check the input value to see if it is composed of digits and then cast it to the desired type or assign a default value else:
import re
is_number = re.compile(r'^[-+]?[0-9]*\.?[0-9]+$')
src_x = input('enter blast x: ')
src_y = input('enter blast y: ')
src_z = input('enter blast z: ')
rcv_x = input('enter receiver x: ')
rcv_y = input('enter receiver y: ')
rcv_z = input('enter receiver z: ')
src_x = float(src_x) if is_number.match(src_x) else 0
src_y = float(src_y) if is_number.match(src_y) else 0
src_z = float(src_z) if is_number.match(src_z) else 0
rcv_x = float(rcv_x) if is_number.match(rcv_x) else 0
rcv_y = float(rcv_y) if is_number.match(rcv_y) else 0
rcv_z = float(rcv_z) if is_number.match(rcv_z) else 0
Input always returns a string. You could do variable = int(number inputted).
Also, just use a try/except statement and assign a default value in the except clause
>
Try:
Num1 = int(input("Enter a number"))
#mathematical function or whatever
Except Exception as e:
Num1=int(10) #or whatever default number
print(e) #for troubleshooting

EOF when reading a line

This is error is point towards this line of code:
s = str(input("Enter the String to be reversed:"))
def print_backward(string):
if len(string) == 0:
return string
else:
return print_backward(string[1:]) + string[0]
s = str(input("Enter the String to be reversed:"))
print(print_backward(s))
This appears to work perfectly. Maybe include something like this to make input work on Python 2 and 3.
try:
input = raw_input
except NameError:
pass

Categories