getting a blank string from output - python

I am having a hard time with understanding whats going on with this piece of code. the goal is to output a blank string if both of the names are missing. my code just outputs "Name: " no matter what i use for a return value????
def format_name(first_name, last_name):
if len(first_name) and len(last_name) !=0:
return "Name: " + str(last_name) +", " + str(first_name)
elif len(last_name) == 0:
return "Name: " + str(first_name)
elif len(first_name) == 0:
return "Name: " + str(last_name)
else:
return ""

The problem is that if both strings are empty, then one string is empty, too. You have to re-arrange your conditions or the last one will never be triggered. Also, but unrelated to the problem, you can just check if string to check whether string is non-empty. Also, no need to convert the names to str (assuming that they are str already).
def format_name(first_name, last_name):
if first_name and last_name: # both
return "Name: " + last_name +", " + first_name
elif not (first_name or last_name): # neither
return ""
elif last_name: # not both or neither, so only first
return "Name: " + last_name
else: # not both, neither, or first, so only last
return "Name: " + first_name
For less if/elif "fun", you could filter and join the non-empty names, if any:
def format_name(first_name, last_name):
present = [x for x in (last_name, first_name) if x]
if present:
return "Name: " + ", ".join(present)
else:
return ""
(The logic of that second one is also much simpler, as evident by the several mistakes I made in the first version, and less code-duplication, too.)

I made a format_name function on my own. Please test it. I'd be very happy if you let me know opinion.
def format_name(first_name, last_name):
name_list = [last_name, first_name]
name_list = [name.strip() for name in name_list if name.strip()]
full_name = ", ".join(name_list).strip()
if full_name:
return "Name: " + full_name
else:
return ""
first_name = ""
last_name = ""
full_name = format_name(first_name, last_name)
print(full_name)

You will need to rearrange the conditions to be able to check if both parts of the name are empty before you check for each individually.
def f_n(first_name, last_name):
if len(first_name) != 0 and len(last_name) !=0:
return "Name: " + str(last_name) +", " + str(first_name)
elif len(last_name) == 0 and len(first_name) == 0:
return " "
elif len(last_name) == 0:
return "Name: " + str(first_name)
else:
return "Name: " + str(last_name)

def format(first_name, last_name):
if len(first_name) != 0 and len(last_name) !=0:
return "Name: " + str(last_name) +", " + str(first_name)
if len(last_name) == 0 and len(first_name) == 0:
return " "
if len(last_name) == 0:
return "Name: " + str(first_name)
if len(first_name) == 0:
return "Name: " + str(last_name)

Related

How can I refactor this python script better?

I am expected to ensure the code is written without unnecessary lines of code. Is there a way to refactor this and get the same output?
def format_name(first_name, last_name):
if len(first_name) > 0 and len(last_name) > 0:
return("Name: " + last_name + ", " + first_name)
elif len(first_name) > 0 or len(last_name) > 0:
return("Name: " + first_name + last_name)
else:
empty_string = ""
return empty_string
return string
print(format_name("Ernest", "Hemingway"))
# Should return the string "Name: Hemingway, Ernest"
print(format_name("", "Madonna"))
# Should return the string "Name: Madonna"
print(format_name("Voltaire", ""))
# Should return the string "Name: Voltaire"
print(format_name("", ""))
# Should return an empty string
Without getting "too golfie", this should do the trick:
def format_name(first_name, last_name):
name = f"{first_name}, {last_name}".strip(", ")
return f"Name: {name}" if name else ""
The refactored method tries to allocate the logic of the function in a single if condition.
def format_name(first_name, last_name):
result = ''
sep = ', ' if first_name and last_name else ' '
if first_name or last_name:
result = last_name + sep + first_name
result = 'Name: ' + result.strip()
return result
print(format_name("Ernest", "Hemingway")) # "Name: Hemingway, Ernest"
print(format_name("", "Madonna")) # "Name: Madonna"
print(format_name("Voltaire", "")) # "Name: Voltaire"
print(format_name("", "")) # `empty_string`
Use str.join and filter to build the name string:
def format_name(first_name, last_name):
full_name = ", ".join(filter(None, (last_name, first_name)))
if full_name:
full_name = "Name: " + full_name
return full_name

Need to make str method return string instead of printing

I need the below str method written to return a string rather than print a string.
def __str__(self):
"""Returns the string representation of the student."""
avg = sum(self.scores) / len(self.scores)
print("Name: " + str(self.name))
print("Score 1: " + str(self.scores[0]))
print("Score 2: " + str(self.scores[1]))
print("Score 3: " + str(self.scores[2]))
print("High: " + str(int(max(self.scores))))
print("Average: %.2f\n" % avg)
What you want to do is convert all those print statements into one string, while maintaining the newlines that you already have.
Something like this should work in place of str
def __str__(self):
avg = sum(self.scores) / len(self.scores)
s = ""
s += "Name: " + str(self.name) + "\n"
s += "Score 1: " + str(self.scores[0]) + "\n"
s += "Score 2: " + str(self.scores[1]) + "\n"
s += "Score 3: " + str(self.scores[2]) + "\n"
s += "High: " + str(int(max(self.scores))) + "\n"
s += "Average: %.2f\n" % avg + "\n"
return s

How do I display an entire object that matches my search by an attribute of that object in Python?

I am writing a program that keeps track of the animals on a farm and I want to be able to search for an animal by e.g: name, gender, age etc, which all are attributes to the objects. I am a complete noob when it comes to Python so all help is very appreciated.
Here is the code i have so far for this, but it only ads the attribute that is searched for to the list and then prints it. I want to be able to add the entire object to the list and print the whole object through that list.
class Djur:
def __init__(self, art, namn, ålder, kön, gravid):
self.art = art
self.namn = namn
self.age = ålder
self.gender = kön
self.gravid = gravid
def __str__(self):
return ("Art: " + str(self.art) + " " + "\n"
"Namn: " + str(self.namn) + " " + "\n"
"Ålder: " + str(self.age) + " " + "\n"
"Kön: " + str(self.gender) + " " + "\n"
"Gravid: " + str(self.gravid))
def __repr__(self):
return str(self)
try:
val2 = input("Ange sök-text")
l=[]
for x in djurlista:
y = x.art or x.gender or x.namn or x.gravid or x.age
if y == val2:
l.append(x.art)
print(l)
meny()
except ValueError:
print("Var god välj ett giltigt alternativ!")
To create a list with the objects you just need to write l.append(x) instead of l.append(x.art). Now you are just appending the property art.

Python string index out of range error?

I'm attempting to convert names from a first name first style to a family name first. The trick is getting it to accept input with or without a middle name.
My code as it stands:
import re
def convertName(oldName):
newName = oldName
while newName == oldName:
newName = re.sub('^ +', '',oldName)
newName = re.sub(' +', ' ',newName)
return newName
def main(firstName, middleName, lastName):
finalName = (lastName + firstName + middleName)
return finalName
name = 0
while name != "":
name = str(input("Name ---- "))
if name == "":
print("Finished")
break
newName = convertName(name)
firstNameSplit = newName.find(" ")
firstName = newName[:firstNameSplit]
lastNameSplit = newName.rfind(" ") + 1
lastName = newName[lastNameSplit:] + ', '
middleNameSplit = newName[firstNameSplit:lastNameSplit]
middleName = middleNameSplit.strip()
finalMiddleName = " " + middleName[0] + '.'
finalName = main(firstName, finalMiddleName, lastName)
print("Result --",finalName)
print()
My current results:
Name ---- joshua example example
Result -- example, joshua e.
Name ---- joshua example
Traceback (most recent call last):
line 37, in 0
builtins.IndexError: string index out of range
Any tips/hints would be much appreciated!!
Eventually found out a working solution in the following:
newName = convertName(name)
firstNameSplit = newName.find(" ")
firstName = newName[:firstNameSplit]
lastNameSplit = newName.rfind(" ") + 1
lastName = newName[lastNameSplit:] + ', '
middleNameSplit = newName[firstNameSplit:lastNameSplit]
middleName = middleNameSplit.strip()
if middleName != "":
finalMiddleName = " " + middleName[0] + '.'
else:
finalMiddleName = ""
finalName = main(firstName, finalMiddleName, lastName)
print("Result --",finalName)
print()
Or you could just do the following:
name = str(input("Name ---- "))
if len(name.split()) == 2:
print("Result -- " + name[name.rfind(" "):] + ", " + name[:name.find(" ")] + " " + name[name.find(" ")+1] + ".")
if len(name.split()) == 1:
print ("Result -- " + name[name.find(" "):] + ", " + name[:name.find(" ")])
else:
print ("Sorry! Invalid name")
This implementation has only been tested in Python 2.7.5.
It uses the string methods .find() and .rfind() to find the indices of the start of the first name, middle name, and last name
len(name.split()) tests how many words are in the name.
Your problem:
string = ""
print(string[0])
returns an error.
so, I fixed your main function, but you'll have to re-write the parser:
def main(firstName, lastName, middleName=""):
if(middleName == ""):
finalName = (lastName + " " + firstName)
else:
finalName = lastName + " " + firstName + " " + middleName[0] + "."
return finalName

python list duplicating instead of concatenating

class Rating():
def __init__(self, user, item, rating):
self.user = user
self.item = item
self.rating = rating
def __str__(self):
return str(user) + " " + str(item) + " " + str(rating)
def __repr__(self):
return str(user) + " " + str(item) + " " + str(rating)
data = open('data.dat').readlines()
records = ()
for i in data:
user, item, rating = i.split()
r = Rating(user, item, rating)
records += (r,)
print records
data = [A, B, C], I'd expect records to have (<Record> A, <Record> B, <Record> C). But instead it contains (<Record> C, <Record> C, <Record> C)?
You are not using the class attributes, but the global variables you have defined by chance.
return str(user) + " " + str(item) + " " + str(rating)
Should look like
return str(self.user) + " " + str(self.item) + " " + str(self.rating)
Your class's __str__ is reference global names:
def __str__(self):
return str(user) + " " + str(item) + " " + str(rating)
Which will be the last iteration of:
user, item, rating = i.split()
That needs to be fixed to be self.user, self.item etc...
Also I would change your line to be the more efficient and Pythonic:
records = [Rating(*line.split()) for line in data]

Categories

Resources