Trying to figure out how I can return multiple values from a function. I've tried and searched for information and it seems I should be using tuples.
Here's a normal recursive function (copied from another stackoverflow question):
def backward(text):
if text == '':
return text
else:
return text[-1] + backward(text[:-1])
Now, let's say I want the function to return both the reversed text but also the initial text in a tuple. How would I make it work?
What I am trying to get:
>>> print(backward('hello'))
('olleh','hello')
Keep getting errors like "Can't convert 'tuple' object to str implicitly". Got any ideas?
Thanks.
You don't need recursion for this
def backward(text):
if text == '':
return text
else:
return text[::-1], text
def backward(text):
return (backwardImpl(text), text)
def backwardImpl(text):
if text == '':
return text
else:
return text[-1] + backwardImpl(text[:-1])
>>> print(backward('hello'))
('olleh','hello')
Version with one function:
def backward(text, recursiveCall = False):
if not recursiveCall:
return (backward(text, True), text)
if text == '':
return text
else:
return text[-1] + backward(text[:-1], True)
However if client calls with second argument set to True it will spoil the result.
Related
Create a function called initials that takes in a persons names and then returns the initials. You should pass the names using **args.
For example for James Marshall Hendrix it should return J.M.H.
Or, for John Ronald Reuel Tolkien it should return J.R.R.T (one *arg to rule them all).
My outputs are JMH AND JRRT But i need to output them as the ones above.
def initials(*args):
result = ""
for word in args:
result += word[0].upper()
return result
if __name__ == "__main__":
print(initials("James", "Marshall", "Hendrix")) # should print the return value of "J.M.H"
print(initials("John", "Ronald", "Reuel", "Tolkien")) # should print the return value of "J.R.R.T"
def initials(*args):
result = []
for word in args:
result.append(word[0])
return ".".join(result)
if __name__ == "__main__":
print(initials("James", "Marshall", "Hendrix")) # should print the return value of "J.M.H"
print(initials("John", "Ronald", "Reuel", "Tolkien")) # should print the return value of "J.R.R.T"
Here is the fixed code, we store the result in a list instead of a string like how you did before, and we join the list with . at the end.
You can compact all that with a list comprehension:
def initials(*args):
return '.'.join([n[0] for n in args])
print(initials("James", "Marshall", "Hendrix"))
# J.M.H
print(initials("John", "Ronald", "Reuel", "Tolkien"))
# J.R.R.T
Edit: (thanks to azro): you can simplify it even further using a generator; it will be slower though (read ShadowRanger's very interesting comment below):
return '.'.join(n[0] for n in args)
Hi you can just add a "." when you take the first letter and then you can just return it without the first character anyway this method can
implement in any other programming language.
def initials(*args):
result = ""
for word in args:
result +="."+ word[0].upper()
return result[1:]
if __name__ == "__main__":
print(initials("James", "Marshall", "Hendrix"))
print(initials("John", "Ronald", "Reuel", "Tolkien"))
How do I get otherImages to return the string in it so that I can replace a word within it when called from 'narrow' method?
def otherImages(self):
self.wfile.write(bytes("<div id='menu_button'><a href='/narrow'><img src='../images/menu_button.png'></a></div>", "utf8"))
#^word I want to replace
def contentList(self, skip_name=''): # All content methods in list
methods = [self.title, self.containerDIV, self.heading, self.stopSection, self.offlineSection, self.onlineSection, self.endDIV, self.otherImages]
for m in methods:
if m.__name__ != skip_name:
m()
def narrow(self):
try:
self.reply()
self.contentList('onlineSection') # removed onlineSection
for words in self.otherImages():
words.replace("narrow", "index")
self.otherImages doesn't return anything! When a function does not return an explicit value in python, it returns None. You cannot iterate over None.
Here are the changes I made which solves my problem. It allows me to edit the string when called from the 'narrow' method.
def otherImages(self):
return["<div id='menu_button'><a href='/narrow'><img src='../images/menu_button.png'></a></div>"]
def narrow(self):
try:
self.reply()
self.contentList('onlineSection') # removed onlineSectionv
for words in self.otherImages():
words = words.replace("/narrow", "/")
self.wfile.write(bytes(words, "utf8"))
return
in fucntion getLink(urls), I have return (cloud,parent,children)
in main function, I have (cloud,parent,children) = getLink(urls) and I got error of this line: TypeError: 'NoneType' object is not iterable
parent and children are all list of http links. since, it is not able to paste them here, parent is a list contains about 30 links; children is a list contains about 30 items, each item is about 10-100 links which is divide by ",".
cloud is a list contain about 100 words, like that: ['official store', 'Java Applets Centre', 'About Google', 'Web History'.....]
I didnot know why I get an error. Is there anything wrong in passing parameter? Or because the list take too much space?
#crawler url: read webpage and return a list of url and a list of its name
def crawler(url):
try:
m = urllib.request.urlopen(url)
msg = m.read()
....
return (list(set(list(links))),list(set(list(titles))) )
except Exception:
print("url wrong!")
#this is the function has gone wrong: it throw an exception here, also the error I mentioned, also it will end while before len(parent) reach 100.
def getLink(urls):
try:
newUrl=[]
parent = []
children =[]
cloud =[]
i=0
while len(parent)<=100:
url = urls[i]
if url in parent:
i += 1
continue
(links, titles) = crawler(url)
parent.append(url)
children.append(",".join(links))
cloud = cloud + titles
newUrl= newUrl+links
print ("links: ",links)
i += 1
if i == len(urls):
urls = list(set(newUrl))
newUrl = []
i = 0
return (cloud,parent,children)
except Exception:
print("can not get links")
def readfile(file):
#not related, this function will return a list of url
def main():
file='sampleinput.txt'
urls=readfile(file)
(cloud,parent,children) = getLink(urls)
if __name__=='__main__':
main()
There might be a way that your function ends without reaching the explicit return statement.
Look at the following example code.
def get_values(x):
if x:
return 'foo', 'bar'
x, y = get_values(1)
x, y = get_values(0)
When the function is called with 0 as parameter the return is skipped and the function will return None.
You could add an explicit return as the last line of your function. In the example given in this answer it would look like this.
def get_values(x):
if x:
return 'foo', 'bar'
return None, None
Update after seing the code
When the exception is triggered in get_link you just print something and return from the function. You have no return statement, so Python will return None. The calling function now tries to expand None into three values and that fails.
Change your exception handling to return a tuple with three values like you do it when everything is fine. Using None for each value is a good idea for it shows you, that something went wrong. Additionally I wouldn't print anything in the function. Don't mix business logic and input/output.
except Exception:
return None, None, None
Then in your main function use the following:
cloud, parent, children = getLink(urls)
if cloud is None:
print("can not get links")
else:
# do some more work
Consider the following:
def funcA():
some process = dynamicVar
if dynamicVar == 1:
return dynamicVar
else:
print "no dynamicVar"
def main():
outcome = funcA()
If the 'some process' part results in a 1, the var dynamicVar is passed back as outcome to the main func. If dynamicVar is anything but 1, the routine fails as no arguments are being return.
I could wrap the outcome as a list:
def funcA():
outcomeList = []
some process = dynamicVar
if dynamicVar == 1:
outcomeList.append(dynamicVar)
return outcomeList
else:
print "no dynamicVar"
return outcomeList
def main():
outcome = funcA()
if outcome != []:
do something using dynamicVar
else:
do something else!
or maybe as a dictionary item. Each of the 2 solutions I can think of involve another set of processing in the main / requesting func.
Is this the 'correct' way to handle this eventuality? or is there a better way?
What is the proper way of dealing with this. I was particularly thinking about trying to catch try: / except: errors, so in that example the uses are reversed, so something along the lines of:
def funcA():
some process = dynamicVar
if dynamicVar == 1:
return
else:
outcome = "no dynamicVar"
return outcome
def main():
try:
funcA()
except:
outcome = funcA.dynamicVar
In Python, all function that do not return a value will implicitly return None. So you can just check if outcome is not None in main().
I believe when you write a function, it's return value should be clear and expected. You should return what you say you will return. That being said, you can use None as a meaningful return value to indicate that the operation failed or produced no results:
def doSomething():
"""
doSomething will return a string value
If there is no value available, None will be returned
"""
if check_something():
return "a string"
# this is being explicit. If you did not do this,
# None would still be returned. But it is nice
# to be verbose so it reads properly with intent.
return None
Or you can make sure to always return a default of the same type:
def doSomething():
"""
doSomething will return a string value
If there is no value available, and empty string
will be returned
"""
if check_something():
return "a string"
return ""
This handles the case with a bunch of complex conditional tests that eventually just fall through:
def doSomething():
if foo:
if bar:
if biz:
return "value"
return ""
So I'm fairly new to Python but I have absolutely no idea why this strong oldUser is changing to current user after I make the parse call. Any help would be greatly appreciated.
while a < 20:
f = urllib.urlopen("SITE")
a = a+1
for i, line in enumerate(f):
if i == 187:
print line
myparser.parse(line)
if fCheck == 1:
result = oldUser[0] is oldUser[1]
print oldUser[0]
print oldUser[1]
else:
result = user is oldUser
fCheck = 1
print result
user = myparser.get_descriptions(firstCheck)
firstCheck = 1
print user
if result:
print "SAME"
array[index+1] = array[index+1] +0
else:
oldUser = user
elif i > 200:
break
myparser.reset()
I don't understand why result doesn't work either... I print out both values and when they're the same it's telling me they're not equal... Also, why does myparser.parse(line) turn oldUser into a size 2 array? Thanks!
** Here's the definition for myparse...
class MyParser(sgmllib.SGMLParser):
"A simple parser class."
def parse(self, s):
"Parse the given string 's'."
self.feed(s)
self.close()
def __init__(self, verbose=0):
"Initialise an object, passing 'verbose' to the superclass."
sgmllib.SGMLParser.__init__(self, verbose)
self.divs = []
self.descriptions = []
self.inside_div_element = 0
def start_div(self, attributes):
"Process a hyperlink and its 'attributes'."
for name, value in attributes:
if name == "id":
self.divs.append(value)
self.inside_div_element = 1
def end_div(self):
"Record the end of a hyperlink."
self.inside_div_element = 0
def handle_data(self, data):
"Handle the textual 'data'."
if self.inside_div_element:
self.descriptions.append(data)
def get_div(self):
"Return the list of hyperlinks."
return self.divs
def get_descriptions(self, check):
"Return a list of descriptions."
if check == 1:
self.descriptions.pop(0)
return self.descriptions
Don’t compare strings with is. That checks if they’re the same object, not two copies of the same string. See:
>>> string = raw_input()
hello
>>> string is 'hello'
False
>>> string == 'hello'
True
Also, the definition of myparser would be useful.
I'm not quite sure what your code is doing, but I suspect you want to use == instead of is. Using is compares object identity, which is not the same as string equality. Two different string objects may contain the same sequence of characters.
result = oldUser[0] == oldUser[1]
If you're curious, for more information on the behaviour of the is operator see Python “is” operator behaves unexpectedly with integers.