Python - Random baby name generator issues - (duplicating input, calling variables) - python

I've been looking at this all afternoon and can't figure out why the gender input is repeating itself despite only appearing to be called once. It's not part of a loop that I can see either.
I've tried adding variables to act as a counter and tried using an if statement to only run the input if the counter variable is less than 1, but can't figure it out.
Edit: Thanks to the great feedback here, I found out that get_full_name was causing the duplicating gender input in get_first_name - but now I'm running into issues when trying to output the randomly generated first & middle names.
I figured setting the setFirst, setMiddle and setLast variables as globals, but then I get a NameError. I also tried creating a new function to display them, but that wasn't working either. I tried adding "self." (without the quotes) either directly in the function() or one of the indents beneath it.
I'll display the error first, then the full code.
Error:
Traceback (most recent call last):
File "init.py", line 100, in
main()
File "init.py", line 92, in main
print displayName(setFirst, setMiddle, setLast)
NameError: global name 'setFirst' is not defined
I also get name errors trying to concatenate setFirst, setMiddle and setLast into another variable for the full name.
Here's the code:
from os.path import abspath, join, dirname
import random
full_path = lambda filename: abspath(join(dirname(__file__), filename))
FILES = {
'first:male': full_path('dist.male.first'),
'first:female': full_path('dist.female.first'),
'last': full_path('dist.all.last'),
}
def get_name(filename):
selected = random.random() * 90
with open(filename) as name_file:
for line in name_file:
name, _, cummulative, _ = line.split()
if float(cummulative) > selected:
return name
def get_first_name(gender=None):
global determine
global setFirst
print ("First name... Enter 1 for Male, 2 for Female or 3 to be surprised! ")
determine = input()
if determine == 1:
gender = 'male'
if determine == 2:
gender = 'female'
if determine == 3:
print ("You want to be surprised!")
gender = random.choice(('male', 'female'))
return get_name(FILES['first:%s' % gender]).capitalize()
setFirst = get_first_name()
print setFirst + " "
def get_middle_name(gender=None):
global setMiddle
if determine == 1:
gender = 'male'
if determine == 2:
gender = 'female'
if determine == 3:
gender = random.choice(('male', 'female'))
return get_name(FILES['first:%s' % gender]).capitalize()
setMiddle = get_middle_name()
print setMiddle + " "
def get_last_name():
global setLast
#We will implicitly pass a Last Name until other issues are fixed
return “Smith”
setLast = get_last_name()
print setLast
def get_full_name(gender=None):
return u"%s %s %s" % (get_first_name(gender), get_middle_name(gender), get_last_name())
#def displayName(setFirst, setMiddle, setLast):
# print setFirst + " " + setMiddle + " " + setLast
def main():
#print u"%s %s %s" % (setFirst, setMiddle, setLast)
#print displayName(setFirst, setMiddle, setLast)
f = open('output', 'a') #append output to filename output
f.write(get_full_name() + '\n') #and add a line break after each run
f.close()
if __name__ == "__main__":
main()
Even if I try passing the variables to main() like:
def main(setFirst, setMiddle, setLast):
It still gives the NameError about not being defined. What am I doing wrong?
I added this right under "import random", but now I'm getting some rogue "None" displays - which leads me to believe there is a leak in the code somewhere. Thoughts?
setFirst = None
setMiddle = None
setLast = None
Here is the function I created to try to track it:
def displayName(setFirst, setMiddle, setLast):
if setFirst == None:
print ("Random Baby Name Generator")
else:
print setFirst
print setMiddle
print setLast
if setMiddle == None:
print ("Double check the middle name variable.")
if setLast == None:
print ("Double check the last name variable.")

You are calling get_full_name() twice, you need to save the results:
def main():
full_name = get_full_name()
print(full_name)
f = open('output', 'a') #append output to filename output
f.write(full_name + '\n') #and add a line break after each run
f.close()
You also have a few indentation issues as well, plus your use of globals is a bit inefficient. Ideally, functions should do one - and only one - task; this makes them easier to debug.
Try this different version of your code:
from os.path import abspath, join, dirname
import random
full_path = lambda filename: abspath(join(dirname(__file__), filename))
FILES = {
'first:male': full_path('dist.male.first'),
'first:female': full_path('dist.female.first'),
'last': full_path('dist.all.last'),
}
GENDER_MAP = {'1': 'male', '2': 'female'}
def get_gender():
result = input('Select a gender: 1 for Male, 2 for Female or 3 to be surprised')
if result not in ('1', '2', '3'):
print('{} is not a valid choice, please try again'.format(result))
return get_gender()
if result == '3':
return random.choice(('1', '2'))
return result
def get_name(filename):
selected = random.random() * 90
with open(filename) as name_file:
for line in name_file:
name, _, cummulative, _ = line.split()
if float(cummulative) > selected:
return name
def get_name_from_file(name_type='first', gender='male'):
if name_type in ('first','middle',):
name = get_name(FILES['{}:{}'.format(name_type, gender)]).capitalize()
else:
name = get_name(FILES['last']).capitalize()
return name
def get_full_name():
gender = get_gender()
gender_file = GENDER_MAP.get(gender, '')
first_name = get_name_from_file('first', gender_file)
middle_name = get_name_from_file('middle', gender_file)
last_name = get_name_from_file('last')
return '{} {} {}'.format(first_name, middle_name, last_name)
if __name__ == '__main__':
name = get_full_name()
print(full_name)
with open('output', 'a') as f:
f.write('{}\n'.format(full_name))
print('Done')

get_full_name is being called twice, probably, and this result in other functions referenced by get_full_name being called twice as well. Unfortunately this means double input and confusing the user.

Related

Why an extra none type str is returning?

Here is my code in Python for returning a string in capitalized :
import math
import os
import random
import re
import sys
def solve(s):
name = list(s.split())
for i in range(len(name)):
nparts = name[i].capitalize()
return print (nparts, end = " ")
if __name__ == '__main__':
fptr = open(os.environ['OUTPUT_PATH'], 'w')
s = input()
result = solve(s)
fptr.write(result + '\n')
fptr.close()
When I run only the function then the result is ok, but when I try to write the result in a file then I get the error below :
fptr.write(result + '\n')
TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'
By manually checking I found that when I am storing the result into the result variable it also gets an extra value "None". I have no idea why this is going on. Please help.
Your def solve(s): function doesn't return anything so by default it returns None
Fix it to:
def solve(s):
name = list(s.split())
return name
To capitalize each word a sentence :
split it
loop on it to capitalize each word
join them by space
import os
def solve(sentence):
return " ".join(word.capitalize() for word in sentence.split())
if __name__ == '__main__':
s = input("Give a sentence: ")
result = solve(s)
with open(os.environ['OUTPUT_PATH'], 'w') as fptr:
fptr.write(result + '\n')
When the programmer does not define functions to return anything, Python function by default return None. This is the thing that is happening in your program.
The function solve does not return anything and so returns None which gets stored in the variable result when the function is called
A change that you can make in your program is to return the name.
def solve(s):
name = list(s.split())
return name
Also, in your program, a return statement cannot be used within a for block.
Moreover, name is not defined in your main program. A tip to fix it would be to change the variable name from name to result in your for loop and place the for block after calling the function:
if __name__ == '__main__':
fptr = open(os.environ['OUTPUT_PATH'], 'w')
s = input()
name = solve(s)
for i in range(len(name)):
nparts = name[i].capitalize()
print (nparts, end = " ")
fptr.write(name[0] + '\n')
fptr.close()

Manipulating Strings to return concatenated username

Whenever I try to display the Firstname with first initial attached to the end, I get an out of string index range error!
def ForeName():
return raw_input("Please enter your Forename: ")
def MiddleName():
return raw_input("please enter your middle name, if none leave blank: ")
def LastName():
return raw_input("Please enter your last name: ")
def Test():
ForeNameT = ForeName()
MiddleNameT = MiddleName()
LastNameT = LastName()
if not MiddleNameT:
first_username = ForeNameT[0:] + LastNameT[0]
elif ForeNameT:
first_username = ForeNameT[0:][0] #i want to display the first name with the initial of the first name attached to the end of the first name.
else:
first_username = ForeNameT[0:] + MiddleNameT[0]
return first_username
print Test()
You can add an argument to Test function by doing def Test(name_method): and then set if to if name_method == 'without_middlename':.
Try to figure out yourself what you would change print Test() to.
I think i know what you are trying to do, try changing your Test function:
def Test():
ForeNameT = ForeName()
MiddleNameT = MiddleName()
LastNameT = LastName()
if not MiddleNameT:
first_username = ForeNameT + LastNameT
else:
first_username = ForeNameT + MiddleNameT + LastNameT
return first_username
notice the changes to the variable names vs. the function names and the return value so print has something to actually print

Difficulties with an unruly program

I have been working on this code for a couple of hours now, and I am rather unsure what the problem is.
import random#imports random
import os#Imports os
print("Welcome to the maths quiz") # Welcomes user to quiz
score = (0)
def details():
plr_name = input ("Please Input Name:") # Asks user for name
plr_class = input("Input class number: ") # Asks the user for class numer
return (plr_name, plr_class)
def Q():
while qno < 10: # loops while qno is under 10
ran_num1 = random.randint(1,99) # Generates the first random number
ran_num2 = random.randint(1,99) # Generates the second random number
ran_fun = random.choice("X-+") # Picks a random function
print(ran_num1,ran_fun,ran_num2,"=") # Prints the Sum for the user
if ran_fun == "X":
sum_ans = ran_num1 * ran_num2 # Does the sum if it is a multiplication
if ran_fun == "+":
sum_ans = ran_num1 + ran_num2 # Does the sum if it is a addition
if ran_fun == "-":
sum_ans = ran_num1 - ran_num2 # Does the sum if it is a subtraction
plr_ans = int(input()) # Gets the user's answer
if plr_ans == sum_ans:
print("Correct!") # Prints correct
score = score + 1 # Adds 1 to score
else:
print("Incorrect!")
qno = qno + 1 # Adds 1 to qno
def plr_list_make(lines, listoreder):
index = 0
plr_names =[]
plr_scores =[]
for line in lines:
if listorder == 1:
column =0
rev = False
else:
column = 1
rev = True
return sorted(zip(plr_names, plr_scores),key = lambda x:(x[column]),reverse = rev)
def fileUP(plr_name, score, line ):
found = False
index = 0
for line in lines:
if line.startswith(plr_name):
line = line.strip("\n") + ","+str(score+"\n")
lines[index] = line
found = True
index = index + 1
if not found:
lines.append(plr_name+"|" +str(score)+"\n")
return lines
def save (plr_name, plr_class, score):
filename = "QuizScore_"+plr_class+".txt"
try:
fileI = open(filename)
except IOError:
fileI = open(filename, "w+")
fileI = open(filename)
lines = fileI.readlines()
fileI.close
lines = FileUP(plr_name, score, lines)
fileO = open(filename, "w")
fileO.writelines(lines)
fileO.close
def disp_list(): ## intialise_list
student_list=[]
filename = "QuizScore_"+plr_class+".txt"
try:
## open file read into list "lines"
input_file = open(filename)
lines = input_file.readlines() ## read file into list "lines"
input_file.close
student_list = create_student_list(lines, listorder) ### update "lines" with student list as requested by user
## output sorted list
for counter in range(len(student_list)):
print ("Name and Score: ", student_list[counter][0], student_list[counter][1])
except IOError:
print ("no class file!!!")
def menu():
print ("1 Test")
print ("2 Alphabetical")
print ("3 Highscore")
print ("4 Avg Score")
def Run():
selection = 0
while selection != 5:
menu()
option = int(input("Please select option: "))
if option == 1:
name, plr_class = details()
save(name, plr_class, Q())
else:
plr_class = input("input class ")
disp_list(plr_class, option-1)
Run()
Errors:
Traceback (most recent call last):
File "C:\Users\user\Documents\CharlieStockham\cgsca\ca2.py", line 117, in
Run()
File "C:\Users\user\Documents\CharlieStockham\cgsca\ca2.py", line 113, in Run
save(name, plr_class, Q())
File "C:\Users\user\Documents\CharlieStockham\cgsca\ca2.py", line 74, in save
lines = FileUP(plr_name, score, lines)
NameError: global name 'FileUP' is not defined
Line 110:
name, plr_class = details()
But the details function does not return anything - so Python tries to assign the default return value None to the tuple name, plr_class. It can't do this, because None is not an iterable (you can't assign two things to it). To fix it, add the following line to your details function:
return (plr_name, plr_class)
(I haven't tested this.)
I like your game but it's buggy as a mofo :P
score and qno aren't properly defined. Define them in the functions that need them, define them globally or pass them to the relevant functions as arguments.
details() doesn't return anything but you still attempt to use its output to define two other variables. Add return (plr_name, plr_class) to details()
Every time you cast user input to int without checking its value, your program will crash if an int can't be cast. This applies here:
option = int(input("Please select option: "))
here
plr_ans = int(input())#Gets the user's answer
and elsewhere.
Since your program is input-heavy you could make a a function to which you pass the expected datatype and an optional string to display to the user. This way you wouldn't have to write try/except 10 times and your program wouldn't crash on unexpected input.
In def fileUP(plr_name, score, line ): you have for line in lines: but lines isn't defined. Thus, the save() function that calls FileUP() also fails. Also, FileUP and fileUP are not the same thing. You call the function with a capital "f" but the defintion of the function calls it fileUP with a lower case "f".
While we're at it, the file handling in def save (plr_name, plr_class, score):looks weird. The standard way of opening files for simple reading and writing in Python is via with open().
disp_list() should take one or two arguments but it doesn't at the moment so this error is raised:
TypeError: disp_list() takes 0 positional arguments but 2 were given
These 2 positional arguments were given here:
disp_list(plr_class, option-1)

calling a variable from outside the function using python

I have this script that allow the user to enter the file name by an argument and then it updates the file version:
#!/usr/bin/env python
import os
import sys
class versionBumper:
def __init__(self):
self.version = None
self.SavedBefore = ""
self.SavedAfter = ""
def change_version(self, file_to_be_modded, packageVersion):
for line in file_to_be_modded:
if packageVersion in line:
print "VERSION FOUND: ", line
self.VersionNumber = line
elif self.VersionNumber is None:
self.SavedBefore += line
else:
self.SavedAfter += line
file_to_be_modded.close()
print "Version: ", self.VersionNumber
return self.VersionNumber
if __name__ == '__main__':
print "sys.argv[1:]:", sys.argv[0:]
versionBumper123 = versionBumper()
filename = sys.argv[1]
path = "/home/Desktop/Crate/Crate/" + filename + "/build/CMakeLists.txt"
if os.path.exists:
inputFile = open(path, 'r')
else:
print "no match found"
sys.exit()
print "Which version number to bump ?"
print "1) major"
print "2) minor."
print "3) patch."
Choose_version = raw_input("Choose version: ")
if Choose_version == "1":
version = versionBumper123.change_version(inputFile, "_MAJOR ")
elif Choose_version == "2":
version = versionBumper123.change_version(inputFile, "_MINOR ")
elif Choose_version == "3":
version = versionBumper123.change_version(inputFile, "_PATCH ")
else:
print "Invalid input. Exiting gracefully..."
sys.exit()
outputFile = open (path, 'w')
splitted_version_line_substrings = version.split('"')
Version_Name = splitted_version_line_substrings[0]
Version_Number = int(splitted_version_line_substrings[1]) + 1
parenthesis = splitted_version_line_substrings[2]
new_version = (str(Version_Name) + '"'
+ str(Version_Number) + '"'
+ str(parenthesis))
print "new_version: ", new_version
outputFile.write(str(versionBumper123.SavedBefore))
outputFile.write(str(new_version))
outputFile.write(str(versionBumper123.SavedAfter))
But I keep getting this error:
Traceback (most recent call last):
File "untitled.py", line 57, in <module>
splitted_version_line_substrings = version.split('"')
NameError: name 'version' is not defined.
I also tried to define version as a global variable but that also did not work, I can't really figure out how to call version from outside the function it is defined in.
Me thinks that you are dealing with a single instance of your class versionBumper
versionBumper123 = versionBumper()
so I guess that what you want to do with the statement
splitted_version_line_substrings = version.split('"')
should be expressed as
splitted_version_line_substrings = versionBumper123.version.split('"')
Just because you use a single instance of your class, imho you could write simpler code if you don't use a class.

Python return function not working for me

I have the following code:
#gets the filename from the user
b= input("Please enter a file name to be opened: ")
a = (b+".txt")
#main data storage and other boolean options
data =[]
result1 =[]
on = True
#File reading in main body with try and except functionality.
try:
check = open(a, 'r')
line =check.readlines()
for items in line:
breakup= items.split()
number, salary, position, first, oname1, oname2, last = breakup
data.append(tuple([last, first + ' ' + oname1 + ' ' + oname2, number, position, salary]))
except IOError as e :
print("Failed to open", fileName)
#Employee creation function, takes the line and stores it in the correct position.
def employee_creation():
result = [((item[0] +", "+ item[1]).ljust(30), int(item[2]), item[3].ljust(15), int(item[4])) for item in data]
for items in result:
result1.append((items[0][0:30], format(items[1], "^5d"), items[2][0:15], "£"+format((items[3]),"<8d")))
return(result)
employee_creation()
print(result)
while on == True:
print("Please select what option you would like to use to search for employees:")
option = int(input("""
1 - Salary (X to X)
2 - Job Titlle
3 - Name, Payroll Number
:"""))
if option == 1:
start = input("What range would you like to start from: ")
end = input("What is the maximum range you would like :")
for items in result:
print(items[3])
if items[3]>start and items[3]<end:
print(items)
else:
print("No employees with this information can be found")
on= False
else:
on= False
However my def employee_creation() doesn't actually return result. I need it to make it a global variable so that I can use it to launch personal querys against the data.
Can anyone see why its not working?
No need to use the evil global variables. You forgot to store the result of your function to another variable.
def employee_creation():
result = [((item[0] +", "+ item[1]).ljust(30), int(item[2]), item[3].ljust(15), int(item[4])) for item in data]
for items in result:
result1.append((items[0][0:30], format(items[1], "^5d"), items[2][0:15], "£"+format((items[3]),"<8d")))
return result # no need for () here
result = employee_creation() # store the return value of your function
print(result)

Categories