I have a list of things I want to iterate over and return each of them only once per function call.
What I've tried:
tl = """
zza,zzb,zzc,zzd,zze,zzf,zzg,zzh,zzi,zzj,zzk,zzl,zzm,zzn,zzo,zzp,zzq,zzr,zzs,zzt,zzu,zzv,zzw,zzx,zzy,zzz
"""
# convert each string into list
result = [x.strip() for x in tl.split(",")]
index = 0
def func():
return result[index]
index += 1
It's saying code unreachable at the index += 1 part.
The output I want is zza the first time I call func(), then zzb, then zzc, etc.
Appreciate the help.
EDIT:
I've found this answer to work well and easily readable:
# list of elements seperated by a comma
tl = """
zza,zzb,zzc,zzd,zze,zzf,zzg,zzh,zzi,zzj,zzk,zzl,zzm,zzn,zzo,zzp,zzq,zzr,zzs,zzt,zzu,zzv,zzw,zzx,zzy,zzz
"""
# split each string by comma to get a list
result = [x.strip() for x in tl.split(",")]
# initialize the object
iterator_obj = iter(result)
print(next(iterator_obj))
print(next(iterator_obj))
print(next(iterator_obj))
output:
zza
zzb
zzc
In c++ there is an operator that will increment a variable with ++i incrementing before evaluation and i++ after evaluation
(i:=i+1) #same as ++i (increment, then return new value)
(i:=i+1)-1 #same as i++ (return the incremented value -1)
so the function you want is
def func():
global index
return result[(index := index+1)-1]
the := operator is new in python 3.8
so
tl = """
zza,zzb,zzc,zzd,zze,zzf,zzg,zzh,zzi,zzj,zzk,zzl,zzm,zzn,zzo,zzp,zzq,zzr,zzs,zzt,zzu,zzv,zzw,zzx,zzy,zzz
"""
# convert each string into list
result = [x.strip() for x in tl.split(",")]
index = 0
def func():
global index
return result[(index := index + 1) - 1]
print(func())
print(func())
print(func())
print(func())
prints
zza
zzb
zzc
zzd
Because return statement exit the function, any statement after that is not reachable. A quick fix to your code:
tl = """
zza,zzb,zzc,zzd,zze,zzf,zzg,zzh,zzi,zzj,zzk,zzl,zzm,zzn,zzo,zzp,zzq,zzr,zzs,zzt,zzu,zzv,zzw,zzx,zzy,zzz
"""
# convert each string into list
result = [x.strip() for x in tl.split(",")]
next_index = 0
def func():
global next_index
next_index += 1
return result[next_index-1]
BTW, your func behaves like built-in next. If you don't want to reinvent the wheel:
# convert each string into iterator
result = (x.strip() for x in tl.split(","))
# next(result) will get to the next item on the list
If you want to be able to only return one item of your string at a time per function call, you need to use an generator:
def func(items):
string_list = items.split(",")
for i in range(len(string_list)):
yield string_list[i]
tl = """
zza,zzb,zzc,zzd,zze,zzf,zzg,zzh,zzi,zzj,zzk,zzl,zzm,zzn,zzo,zzp,zzq,zzr,zzs,zzt,zzu,zzv,zzw,zzx,zzy,zzz
"""
item = func(tl)
To pull a value out, in order, use
next(item) # zza
next(item) # zzb
...
Every time you call next, a new value will be returned.
As an aside, anything after return statement will not run, which is why your index += 1 did not work. Return stops the function from running.
Related
Define a function named how_many_substr_of_string(...) which receives two parameters, the first parameters is a list with strings (name it listst) and the second parameter is a single string (name it st). The function should return a number, indicating how many of the strings in the list listst are substrings in the string st
As an example, the following code fragment:
listst = ["a","bc","dd"]
st = "abc"
res = how_many_substr_of_string(listst,st)
print (res)
should produce the output:
2
My code:
def how_many_substr_of_string(listst, st):
return listst.count(st)
My code does not work for the following conditions and any other related conditions:
listst = ["a","bc","dd"]
st = "abc"
res = how_many_substr_of_string(listst,st)
print (res)
I get the output 0 but its supposed to be 2. How to fix this or edit my code such that it will work for this any other case as shown in the question
def how_many_substr_of_string(listst, st):
return sum(1 for item in listst if item in st)
A note on why this works even though strings are considered arrays - Python will use __contains__(self, item), __iter__(self), and __getitem__(self, key) in that order to determine whether an item lies in a given string.
Use this:
listst = ["a","bc","dd"]
s = "abc"
def how_many_substr(iterable, st):
res = 0
for i in iterable:
if i in st: res += 1
return res
print(how_many_substr(listst, s))
Output:
2
Your code was:
def how_many_substr_of_string(listst, st):
return listst.count(st)
This counts the number of times st occurs in listst, which is 0.
I want to return the final value of the list which is new_list[3] but it return nothing at the end. I can get the final value of new_list[3] by using print function. I am quite confusing about the return function. Is it possible it return new_list[times] when the 2 for loop is ended?
original_list = [100,300,400,900,1500]
def filter_list(_list,times):
L = len(_list)
new_list = [list(_list) for k in range(times+1)]
for k in range (0,times):
for j in range (0,L):
if j == 0: #exclude the term [j-1] because new_list[-1] is not exist
new_list[k+1][j] = int(new_list[k][j]*0.2 + new_list[k][j+1]*0.5)
elif j == L-1: #exclude the term [j+1] because new_list[L] is not exist
new_list[k+1][j] = int(new_list[k][j-1]*0.4 + new_list[k][j]*0.2)
else:
new_list[k+1][j] = int(new_list[k][j-1]*0.4 + new_list[k][j]*0.2 + new_list[k][j+1]*0.5)
return (new_list[times])
filter_list(original_list,3)
A function is able to "return" a value back to the scope that called it. If this variable is not stored or passed into another function, it is lost.
For instance:
def f(x):
return x + 1
f(5)
will not print anything since nothing is done with the 6 returned from the f(5) call.
To output the value returned from a function, we can pass it to the print() function:
print(f(5))
or in your case:
print(filter_list(original_list, 3))
This is what the return function does:
A return statement ends the execution of the function call and "returns" the result, i.e. the value of the expression following the return keyword, to the caller. If the return statement is without an expression, the special value None is returned.
You are returning the item but not assigning it to anything
x = filter_list(original_list,3)
print(x)
What this will do is assign whatever you return from your function call to a variable in this case x and then your variable will hold whatever you returned so now
Heres a simple model to visualize this
def something():
x = 1
return x
def something_print():
x = 1
return print(x)
a = something()
print(a)
something_print()
(xenial)vash#localhost:~/python/stack_overflow$ python3.7 fucntion_call.py
1
1
So, the code outlined below sends arguments to a function I've created called bsearch and I want the function main() to send the arguments with the key argument scaled down by 1 from 11 (11,10,9,8,7...) until it reaches 0 an I want the value count outputted each time --- currently it only returns the first count. How do I get it to return after each while loop?
def main():
ilist = [x+1 for x in range(10)]
key = 11
start = 0
end = 10
while key > 0:
count = b(ilist,key,start,end)
key = key -1
return count
I think you might want to look at a few tutorials but I imagine you want something like this:
def main():
count_list = []
for x in range(1,11):
count_list.append(bsearch(x)) # append your results to a list
return count_list # return out of the scope of the loop
or using a list comprehension as suggested in the comments:
def main():
return [bsearch(x) for x in range(1,11)]
So I have a function like this:
def demo_range(limit):
value = 0
while value < limit:
yield value
value = value + 1
and this
def demo_generator_to_list(generator):
return [x for x in range(generator)]
Now in the demo_generator_to_list(generator) I need to fill some code to collapse a generator to:
[0,1,2,3]
from
demo_generator_to_list(demo_range(4))
Just pass the generator to a list() call:
def demo_generator_to_list(generator):
return list(generator)
The list() function will iterate over the generator and add all results to a new list object.
You could still use a list comprehension, but then you don't use range():
return [x for x in generator]
This has no advantage over using list(); it is just slower.
In the following subset problem, I'm trying to make a copy of a list object
def findFourPlus(itemCount, seq, goal):
goalDifference = float("inf")
closestPartial = []
subset_sum(itemCount, seq, goal, goalDifference, closestPartial, partial=[])
print(closestPartial)
def subset_sum(itemCount, seq, goal, goalDifference, closestPartial, partial):
s = sum(partial)
# check if the partial sum is equals to target
if(len(partial) == itemCount):
if s == goal:
print(partial)
else:
if( abs(goal - s) < goalDifference):
goalDifference = abs(goal - s)
print(goalDifference)
print(partial)
print(closestPartial)
closestPartial = copy.deepcopy(partial)
for i in range(len(seq)):
n = seq[i]
remaining = seq[i+1:]
subset_sum(itemCount, remaining, goal, goalDifference, closestPartial, partial + [n])
in the subset function, I am trying to make a copy of the partial list to closestPartial. I've tried
closestPartial = partial
closestPartial = list[:]
closestPartial = list(partial)
closestPartial = copy.copy(partial)
closestPartial = copy.deepcopy(partial)
but in the end all of them seems to be futile. closestPartial remains to be an empty list (which is what I initiated to) for some reason
You are passing closestPartial in as a parameter, so the only thing that will work is an inplace update of its list. All of the examples you give replace the list that was in closestPartial with a new list. But since it wasn't the list you passed in, it doesn't update the real list.
Try:
closestPartial[:] = partial
You can get a feel for the problem by printing the list id before and after the operation.
print id(closestPartial)
...some operation
print id(closestPartial)
if the id changes, that means you created a new list and didn't update the one passed in.
EDIT
Seems I need a better explanation... when you call subset_sum, it creates a local variable called closestPartial that references whatever was passed in as a parameter, in this case a list known to the caller as closestPartial. You now have two variables pointing to the same list. If you reassign the variable, like in closestPartial = partial, those two variables now point to different lists. You didn't update the caller's pointer, you just changed the local variable. Instead, if you don't reassign, changes you make to the one list referenced by both variables are seen by the caller as well - because its the same list.
I suspect that your goalDifference is suffering from the same problem, if you change it in a function and then expect the changed value to somehow get back to the calling function.
Here's some (Python 2 style) code to illustrate what's happening:
#! /usr/bin/env python
def testA(update_func):
seq = []
num = 1
for _ in range(5):
newnum = update_func(seq, num)
print 'testA: ', num, seq, newnum
print
def testB(update_func):
seq = []
num = 1
for _ in range(5):
num = update_func(seq, num)
print 'testB: ', num, seq
print
def update0(seq, num):
#This creates a new list
seq = seq + [num]
num = num + 1
print 'update0:', num, seq
return num
def update1(seq, num):
#This updates the existing list
seq.append(num)
num += 1
print 'update1:', num, seq
return num
def update2(seq, num):
#This updates the existing list
seq[:] = seq + [num]
num += 1
print 'update2:', num, seq
return num
def update3(seq, num):
#This updates the existing list
seq += [num]
num += 1
print 'update2:', num, seq
return num
update_funcs = (update0, update1, update2, update3)
for f in update_funcs:
testA(f)
print '------\n'
for f in update_funcs:
testB(f)
Stack Overflow member Ned Batchelder's article Facts and myths about Python names and values has a good explanation, with cute diagrams.