Multiline list output in doctest - python

I'm testing the result of a function, which returns a list of long strings. Since I have line size limitations, I can't have the whole list on one line.
I already tried printing the list and that works, but I was wondering if there was another way without having to print the result of the function. What I got:
def my_function(input):
r"""Some description.
>>> import pprint
>>> pprint.pprint(my_function("input"))
['long_string_1',
'long_string_2',
'long_string_3']
"""
return list_of_long_strings
Is it possible to do this without printing, just calling the function and having the list with backlashes or something?

You can do it like this
def my_function(input):
r"""Some description.
>>> my_function("input") == ['long_string_1',
... 'long_string_2', 'long_string_3']
True
"""
list_of_long_strings = ['long_string_1', 'long_string_2', 'long_string_3']
return list_of_long_strings

Related

python: how to return two values at different position of calculating in a function?

I want to have a function that process the data in the predefined pipeline, and I need the data at intermediate and final step, so I want to have a function that I can call twice, in the first call, the function returns the intermediate data, and in the second call, the function starts from the last return position and returns the final data, so something like this:
def tworeturns(x):
intermediate = do-something(x)
return intermediate
final = do-something(intermediate)
return final
How to implement this with python?
==========================================================================
Thanks to new-dev-123's answer I was able to return two values, but then I got another problem. After the first yield, I changed the intermediate, and when I call the next for the second time, I want the function to compute based on the modified intermediate, not the original intermediate. Is there a way of doing it?
Using a generator like a coroutine allows you to effectively pause the function and you can drive it using next()
>>> def tworeturns(x):
... print(f"hi {x}")
... yield
... print(f"bye {x}")
... yield
...
>>> corou = tworeturns("bob")
>>> next(corou)
hi bob
>>> next(corou)
bye bob
here's a quick demo I did on cli
So for your example you would do something like:
def tworeturns(x):
intermediate = do-something(x)
yield intermediate
final = do-something(intermediate)
yield final
corou = tworeturns(x)
first_value = next(corou)
second_value = next(corou)
OK, that's a nice question, I sometimes have similar situations.
As one of the comments to your question says, you can use a generator, which literally answers your question.
But I like better the following solution:
def tworeturns(x, intermediate=None):
if intermediate is None:
return do_something(x)
else:
return do_something(intermediate)
Of course, you will now need to call tworeturns with the intermediate result. But it's a clear code, and also, stateless.
Return both values(which will give you a tuple):
def tworeturns(x):
intermediate = do-something(x)
final = do-something(intermediate)
return intermediate, final

Python - why isnt my function outputting 'a' ten times? Beginner question

def testfunction():
for i in range(10):
return('a')
print(testfunction())
I want 'a' outputed 10 times in one line. If I use print instead of return, it gives me 10 'a's but each on a new line. Can you help?
return terminates the current function, while print is a call to another function(atleast in python 3)
Any code after a return statement will not be run.
Python's way of printing 10 a's would be:
print('a' * 10)
In your case it would look like the following:
def testfunction ():
return 'a' * 10
print(testfunction ())
The reason its only printing once is because the return statment finishes the function (the return function stops the loop).
In order to print 'a' 10 times you want to do the following:
def testfunction():
for i in range(10):
print('a')
testfunction()
If you want "a" printed 10 times in one single line then you can simply go for:
def TestCode():
print("a"*10)
There's no need to use the for loop. For loop will just "a" for 10 times but every time it'll be a new line.
You can also take in a function argument and get "a" printed as many times as desired.
Such as:
def TestCode(times):
t = "a"*times
print(t)
Test:
TestCode(5)
>>> aaaaa
TestCode(7)
>>> aaaaaaa
print and return get mixed up when starting Python.
A function can return anything but it doesn't mean that the value will be printed for you to see. A function can even return another function (it's called functional programming).
The function below is adapted from your question and it returns a string object. When you call the function, it returns the string object into the variable called x. That contains all of the info you wanted and you can print that to the console.
You could have also used yield or print in your for loop but that may be outside of the scope.
def test_function(item:str="a", n:int=10):
line = item*n # this will be a string object
return line
ten_a_letters = test_function()
print(ten_a_letters)
"aaaaaaaaaa"
two_b_letters = test_function("b",2)
print(two_b_letters)
"bb"
I want 'a' outputed 10 times in one line. If I use print instead of
return, it gives me 10 'a's but each on a new line.
If you want to use print, the you need to pass a 2nd parameter as follows:
def testfunction():
for i in range(10):
print('a', end='')
However, I think the pythonic way would be to do the following:
def testfunction():
print('a' * 10)
When you use return you end the execution of the function immediately and only one value is returned.
Other answers here provide an easier way to solve your problem (which is great), but I would like to suggest a different approach using yield (instead of return) and create a generator (which might be an overkill but a valid alternative nonetheless):
def testfunction():
for i in range(10):
yield('a')
print(''.join(x for x in testfunction()))
1. What does "yield" keyword do?
def test ():
print('a' * 10)
test()
Output will be 'aaaaaaaaaa'.

A more concise way to write this Python code

In Python, I'd like to test for the existence of a keyword in the output of a Linux command. The keywords to test for would be passed as a list as shown below. I've not spent a lot of time with Python so brute-force approach is below. Is there a cleaner way to write this?
def test_result (result, mykeys):
hit = 0
for keyword in mykeys:
if keyword in result:
hit = 1
print "found a match for " + keyword
if hit == 1:
return True
result = "grep says awk"
mykeys = ['sed', 'foo', 'awk']
result = test_result (result, mykeys)
The any built-in will do it.
def test_result(result, mykeys):
return any(key in result for key in mykeys)
You can use a regular expression to accomplish this. A regular expression of the form a|b|c matches any of a, b or c. So, you'd want something of the form:
import re
p = re.compile('|'.join(mykeys))
return bool(p.search(result))
p.search(result) searches the entire string for a match of the regular expression; it returns a match (which is truth-y) if present and returns None (which is false-y) otherwise. Converting the result to bool gives True if it matches and False otherwise.
Putting this together, you'd have:
import re
def test_result(result, mykeys):
p = re.compile('|'.join(mykeys))
return bool(p.search(result))
You can also make this more concise by not pre-compiling the regular expression; this should be fine if it's a one-time use:
def test_result(result, mykeys):
return bool(re.search('|'.join(mykeys), result))
For reference, read about Python's re library.
Your function does two things, printing and returning the result. You could break them up like so:
def test_result(result, mykeys):
return [k in result for k in mykeys]
def print_results(results):
for result in results:
print("found a match for " + result)
test_result will return a list with all the found keys, or an empty list. The empty list is falsey, so you can use it for whatever tests you want. The print_results is only needed if you actually want to print, otherwise you can use the result in some other function.
If you only want to check for the presence and don't care about which key you found, you can do something like:
def test_result(result, my_keys):
return any(map(lambda k: k in result, mykeys))
If you're using python3 (as you should be), I believe this will be lazy and only evaluate as much of the list as necessary.
See A more concise way to write this Python code for a more concise version of this last function.
To search for an element in a list, you can use a for-else statement. In particular, this allows to return the found element.
def test_result (result, mykeys):
for keyword in mykeys:
if keyword in result: break
else:
return None
return keyword
print(test_result("grep says awk", ['sed', 'foo', 'awk'])) # 'awk'
print(test_result("grep says awk", ['bar', 'foo'])) # None

Python function, overwrite original variable

I have this function:
def icaocode(code):
c.execute("SELECT ICAO, LAT, LON FROM airports WHERE ICAO = ?", (code,))
result = c.fetchone()
if result is None:
print("No airport found with ICAO code", code)
sys.exit()
else:
print("Found", code)
[...]
Lets say I call this function with
icaocode(x)
How do I get the function to overwrite x with the results?
In function def:
def icaocode(code):
...
return code # new value
When calling:
x = icaocode(x)
Btw if the argument is mutable (like a list), you can overwrite it without returning the new value. If it's immutable (like a string, integer), you can't.
E.g.
def f(some_list):
some_list.append("something")
In this case
my_list = []
f(my_list)
my_list will be ["something"]
You can't overwrite the value of the parameter. That is, you can't change it to refer to another object. You can, however, change the object. There is an old thread on pass-by-value and pass-by-reference semantics in Python that you may find illuminating: https://stackoverflow.com/a/986145/399047
For example, you can append elements to a list that is passed in as a parameter. The following code:
def func(a_list):
a_list.append("some value")
l = [1,2,3]
print l
func(l)
print l
would give:
[1,2,3]
[1,2,3,"some value"]
In contrast, a string, cannot be modified. The following code:
def func2(a_str):
a_str += "suffix"
s = "test"
print s
func2(s)
print s
would give:
"test"
"test"
My recommendation, unless you have a good reason, is to avoid mutating your input parameters, and return the modified object instead. Side-effects can make for messy code.
If, at the end of all this you really want to modify your input parameter, one technique would be to wrap the code parameter inside another object. e.g.
def icaocode(code_list):
input_code = code_list[0]
[...]
# do something to input_code, assign result to
# output_code
[...]
code_list[0] = output_code
Then you would call with:
code_list = [code]
icaocode(code_list)
That said, this code is ugly to me, smells something awful, and I don't recommend it.
You can, but it is a horrible way to conduct business. Return the value instead, remember that you can return more than one value if you like. Here is however one way to return a value through a parameter. But don't use it.
>>> def a(b):
... b[0] = 'hi'
....
>>> c = ['nono']
>>> a(c)
>>> print(c)
['hi']

Cast string to first element of a new list in function call

I'm looking for the Python way to take a string and pass it to a function as a list, like so:
word = 'abc'
result = crazyfunction(cast(word,[]))
so that crazyfunction will receive a list like this:
word[0] = 'abc'
instead of a string.
The goal is to cast in the function parameter, instead of having to do an assignment before each call.
From your example, it looks like it would be as simple as building a list. Just call the function like this: crazyfunction(['abc'])
EDIT: Just tested it in the console:
>>> def printfirst(lst):
... print lst[0]
...
>>> printfirst('hello')
h
>>> printfirst(['hello'])
hello

Categories