Python comma separated print changes function behavior [duplicate] - python

This question already has answers here:
Why does this script print an extraneous 'none' in the output
(3 answers)
Closed 9 years ago.
Although I've seen other questions on Python delimiters I haven't been able to find a question answering this so here goes. I'm writing a function that will recursively print an array backwards, and it appears to work just fine:
def print_array_backwards(array):
if (len(array) == 1):
print array[0],
return
print_array_backwards(array[1:])
print array[0],
##########################################
x = [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
print 'Array = ', x
print_array_backwards(x)
Will output:
Array = [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
4 3 2 1 0 4 3 2 1 0
The problem is when I try to print the output of the print_array_backwards function in line with other text, like this:
print 'Array = ', x
print 'The array backwards is', print_array_backwards(x)
This will output:
Array = [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
The array backwards is 4 3 2 1 0 4 3 2 1 0 None
My question is, where does this extra None value come from??
If I push the function output to the next line but leave the comma with the print statement like this:
print 'Array = ', x
print 'The array backwards is',
print_array_backwards(x)
I obviously get the desired output:
Array = [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
The array backwards is 4 3 2 1 0 4 3 2 1 0
Can anyone help me understand why leaving the function in the same line of the print statement causes the function to behave differently?
Thanks for your time!

You are calling a function that does not return anything explicitly. The default return value of such a function is None.
Simply don't print the return value of the function:
print 'Array = ', x
print 'The array backwards is',
print_array_backwards(x)

Change print array[0] to return array[0]. The None comes from the return value of print_array_backwards(), which since you specified nothing is None.

Related

Why isn't for loop resetting the range() function?

I have a code:
x = 6
for y in range(x):
print(y)
x -= 2
It gives: 0, 1, 2, 3, 4, 5
I wrongly predicted that it would give either of these 2 results:
0, 0, 0
Since x goes from 6 to 4 to 2 to 0, there will only be 3 y printed. Also, to my understanding, after each loop, it goes back to the for loop statement, thus resets the range() completely and now every y is 0. I ran the code on PythonTutor and the pointer also seemed to go back to the loop statement after each loop.
0, 1, 2
Since x goes from 6 to 4 to 2 to 0, there will only be 3 y printed. I thought it might be possible that while y takes on the value of the original range (i.e. 6), it would be limited by each new x and thus only have 3 y printed.
Possibility 1 was the most intuitive (albeit wrong) for me and I am not sure how to go about understanding why the answer is as such.
The instance of range produced by range(x) uses the value of x at the time range is called. It does not repeatedly check the value of x each time you need a new value from the range. Your code is effectively the same as
x = 6
for y in [0, 1, 2, 3, 4, 5]:
print(y)
x -= 2
Nothing you do to x has any effect on the range object being iterated.
The range() call creates a range object from x at the start of the loop. Changing x after this has no effect on the range object that is being used to iterate.
If you want to be able to change how many iterations you make in a loop, you probably want to look at using while.
Try this:
# Firstly you assign 6 to the variable x
x = 6
# 'y' will now be assigned to the numbers [0, 1, 2, 3, 4, 5, 6] because the range is 'x' which is 6.
# by printing 'x' it will execute [0, 1, 2, 3, 4, 5, 6] but since x is 'x -2' which is the same as '6 - 2' it will print out the number 6 and -2 until it gets to the range which is -6. the output will be 6 numbers [6, 4, 2, 0, -2, -4]
for y in range(x):
print(x)
x = x - 2
# i am showing you a way of making it give you your expected output [6, 4, 2, 0, -2, -4]

Program Reasoning, python function

Program reasoning requires us to find the input for the function so that it outputs a certain result.
The function is:
def func1(stuff, more_stuff=None):
data = []
for i, thing in enumerate(stuff):
if thing >= 0 or i < 2:
data.append(thing + i)
print(len(stuff))
if more_stuff is not None:
data += more_stuff
print(data)
And the expected output is:
4
[5, 3, 1, 5, -3]
The closest I can get it is:
4
[5, 3, 2, 5, -3]
with func1([5,2,0,2], [-3]) as input
I'm having trouble trying to get the the 1 and I'm just wanting to know how/why you can get a 1 as if it's anything less than 0 ie -1 as value for that index then 'thing' is < 0 and i = 2 so it skips that value/index and the output will be:
4
[5, 3, 5, -3]
The key here is the length of stuff must be 4, NOT the length of data after the first for loop. You're absolutely right that you run into the problem where data[2] can never be 1 if you are trying to use stuff to fill data.
To fix this issue, chop stuff off before that and use more_stuff to append the values you need.
Ie the input you're looking for is:
>>>func1([5, 2, -1, -1], [1, 5, -3])
4
[5, 3, 1, 5, -3]

How to Transfer a number in an array from one position to another

I would like to know how to transfer a number.
For example: [1,0,2,3,4]
Remove the one and transfer the one to two's position
Result: [0,0,1,3,4]
If your manipulations are purely index-based, you can do this:
lst = [1,0,2,3,4]
lst[2] = lst[0]
lst[0] = 0
# [0, 0, 1, 3, 4]
Alternatively, if you need to work out the index of 2:
lst[lst.index(2)] = lst[0]
lst[0] = 0
Since you have not described your question with clear instructions, There is case when there will be more than one 2 or 1 in vector then what you want to do ?
My solution is only for that condition when there is single 1 and 2 in vector because when you use .index method it always returns first value index no matter there are other values too.
Since in your dataset there is always 1 times 1 and 2 in all vector so here is the solution for that
data=[[1, 2, 3, 4, 0], [1, 3, 2, 4, 0], [2, 1, 3, 4, 0] ]
def replace_ (vector_ , replace_value, replace_with):
memory=vector_.index(replace_with)
vector_[vector_.index(replace_value)]=vector_[vector_.index(replace_with)]
vector_[memory]=0
return vector_
for i in data:
print(replace_(i,1,2))
If there are more than one 1 or 2 in vector like [1,0,1,1,2,2] then describe your logic and edit your question for that.

I need to know why this is the output for these python condition

numbers=[i**3 for i in range (10) if i**3%3==1]
print(numbers)
#gets 1,64,343
Why is 1, 64, 343 the answer?
This is equivalent to the code:
for i in range(10):
if (i*i*i) % 3 == 1:
numbers.append(i*i*i)
print (numbers)
You are checking if the remainder obtained when the cube of a number from 1 to 10 is divided by 3 is equal to 1. If it is, you are adding it to a list and printing it.
The meaning of **
ex: 2**3= 2*2*2 #this means 2 to the power 3 = 8
The meaning of %
ex: 5%2= 1 #the sign means module, that means the remaining value after divide 5 by 2, it is one.
in your way, the correct path to write the for each is
for i in range(0,10):
value = i**3
if(value%3 == 1):
print("the value is {0}".format(value))
so the result is :
the value is 1
the value is 64
the value is 343
bit explanation inside the for loop
first get the i = 0, at this point value = 0*0*0 = 0, then value%3=0
then get the i=1, at this point value = 1*1*1 = 1 ,the 'value%3' means 1%3 = 1, so the answer i 1
.... like this see about other conditions also. hope this will help to you.
first i is in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
then if (i*i*i) rem 3 is equal to 1
it selects (i*i*i)
and for [1,4,7]: (1*1*1)%3==1, (4*4*4)%3==1 and (7*7*7)%3==1:
1*1*1=1 and 1/3=0 :remainder=1
4*4*4=64 and 64/3=21 :remainder=1
7*7*7=343 and 343/3=114 :remainder=1
so the output is:
[1*1*1, 4*4*4, 7*7*7] which is [1, 64, 343]
your code:
numbers=[i**3 for i in range (10) if i**3%3==1]
print(numbers)
and this code:
numbers=[]
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
if (i*i*i) % 3 == 1:
numbers.append(i*i*i)
print(numbers)
output this:
[1, 64, 343]

Dictionary works for len(string) multiple of 3. Function deletes remainders but now doesn't translate with dictionary. Python 2.7.1

I made a function with a dictionary. The purpose of the function is to separate the input string into sets of 3 . If the input string value is not a multiple of 3, I want to delete the remainder [1 or 2]
my function was working perfectly until I added the part for deleting the remainders
def func(fx):
d={'AAA':1,'BBB':2,'CCC':3}
length=len(fx)
if length % 3 == 0:
return fx
if length % 3 == 1:
return fx[:-1]
if length % 3 == 2:
return fx[:-2]
Fx=fx.upper()
Fx3=[Fx[i:i+3] for i in range(0,len(Fx),3)]
translate=[d[x] for x in Fx3]
return translate
x='aaabbbcc'
output = func(x)
print output
>>>
aaabbb
the function is recognizing that the input sequence is not a multiple of 3 so its deleting the 2 values which is what i want. However, its splitting the new string into 3 letter words to be translated with my dictionary anymore. If you delete the if statements, the function works but only for strings that are a multiple of 3.
What am I doing wrong ???
You are returning fx when you probably should be reassigning it
def func(fx):
d={'AAA':1,'BBB':2,'CCC':3}
length=len(fx)
if length % 3 == 0:
pass
elif length % 3 == 1:
fx = fx[:-1]
elif length % 3 == 2:
fx = fx[:-2]
Fx=fx.upper()
Fx3=[Fx[i:i+3] for i in range(0,len(Fx),3)]
translate=[d[x] for x in Fx3]
return translate
Here is an alternate function for you to figure out when you know some more Python
def func(fx):
d = {'AAA':1,'BBB':2,'CCC':3}
return [d["".join(x).upper()] for x in zip(*[iter(fx)]*3)]
Does this do what you want?
def func(fx):
d = {'AAA': 1, 'BBB': 2, 'CCC': 3}
fx = fx[:-(len(fx)%3)].upper()
groups = [fx[i:i+3] for i in range(0, len(fx), 3)]
translate = [d[group] for group in groups]
return translate
x='aaabbbcc'
print func(x)
When trimming the end of the string, you were returning the result when you wanted to just store it in a variable or assign it back to fx.
Rather than the if .. elifs you can just use the result of the length modulo 3 directly.
There is no need of a function, it can be done in a one liner less complex than the gnibbler's one.
Acom's solution is nearly mine.
d={'AAA':1,'BBB':2,'CCC':3}
for fx in ('bbbcccaaabbbcccbbbcccaaabbbcc',
'bbbcccaaabbbaaa','bbbcccaaabbbaa','bbbcccaaabbba',
'bbbcccaaabbb','bbbcccaaabb','bbbcccaaab',
'bbbcccaaa','bbbcccaa','bbbccca',
'bbbccc','bbbcc','bbbc',
'bbb','bb','b',''):
print fx
print tuple( d[fx[i:i+3].upper()] for i in xrange(0, len(fx)-len(fx)%3, 3) )
produces
bbbcccaaabbbcccbbbcccaaabbbcc
(2, 3, 1, 2, 3, 2, 3, 1, 2)
bbbcccaaabbbaaa
(2, 3, 1, 2, 1)
bbbcccaaabbbaa
(2, 3, 1, 2)
bbbcccaaabbba
(2, 3, 1, 2)
bbbcccaaabbb
(2, 3, 1, 2)
bbbcccaaabb
(2, 3, 1)
bbbcccaaab
(2, 3, 1)
bbbcccaaa
(2, 3, 1)
bbbcccaa
(2, 3)
bbbccca
(2, 3)
bbbccc
(2, 3)
bbbcc
(2,)
bbbc
(2,)
bbb
(2,)
bb
()
b
()
()
.
I think you have to treat strings that can contain only 3 characters strings 'aaa','bbb','ccc' at the positions 0,3,6,9,etc
Then the preceding programs won't crash if there's an heterogenous 3-characters string at one of these positions instead of one of these set 'aaa','bbb','ccc'
In this case, note that you could use the dictionary's method get that returns a default value when a pased argument isn't a key of the dictionary.
In the following code, I put the default returned value as 0:
d={'AAA':1,'BBB':2,'CCC':3}
for fx in ('bbbcccaaa###bbbccc"""bbbcc',
'bbb aaabbbaaa','bbbccc^^^bbbaa','bbbc;;;aabbba',
'bbbc^caaabbb',']]bccca..bb','bbb%%%aaab',
'bbbcccaaa','bbb!ccaa','b#bccca',
'bbbccc','bbbcc','bbbc',
'b&b','bb','b',''):
print fx
print [d.get(fx[i:i+3].upper(), 0) for i in xrange(0, len(fx)-len(fx)%3, 3)]
produces
bbbcccaaa###bbbccc"""bbbcc
[2, 3, 1, 0, 2, 3, 0, 2]
bbb aaabbbaaa
[2, 0, 1, 2, 1]
bbbccc^^^bbbaa
[2, 3, 0, 2]
bbbc;;;aabbba
[2, 0, 0, 2]
bbbc^caaabbb
[2, 0, 1, 2]
]]bccca..bb
[0, 3, 0]
bbb%%%aaab
[2, 0, 1]
bbbcccaaa
[2, 3, 1]
bbb!ccaa
[2, 0]
b#bccca
[0, 3]
bbbccc
[2, 3]
bbbcc
[2]
bbbc
[2]
b&b
[0]
bb
[]
b
[]
[]
By the way, I preferred to create a tuple instead of a list because for the kind of invariable objects that are in the result, I think it is better not to create a list

Categories