Is it possible to know if generator was used? i.e.
def code_reader(code):
for c in code:
yield c
code_rdr = code_reader(my_code)
a = code_rdr.next()
foo(code_rdr)
After foo call I would like to know if .next() was called on code_rdr by foo or not.
Of course I could wrap it by some class with a counter for next() calls.
Is there any easy way to do so?
Python 3.2+ has inspect.getgeneratorstate(). So you can simply use inspect.getgeneratorstate(gen) == 'GEN_CREATED':
>>> import inspect
>>> gen = (i for i in range(3))
>>> inspect.getgeneratorstate(gen)
'GEN_CREATED'
>>> next(gen)
0
>>> inspect.getgeneratorstate(gen)
'GEN_SUSPENDED'
I have used idea from attached possible answers, bellow is redefined code_reader function:
def code_reader(code):
length = len(code)
i = 0
while i < length:
val = (yield i)
if val != 'position':
yield code[i]
i += 1
by using .send('position') on I would have know position of next item to be generated, i.e.
a = code_reader("foobar")
print a.next()
print a.send('position')
print a.next()
print a.send('position')
print a.send('position')
print a.next()
print a.send('position')
output:
0
0
f
1
1
o
2
Related
def seekNextStation(self):
counter = 0
print(counter)
for counter in range(len(self.stations)):
counter +=1
print(counter)
if counter != 6:
self.currentlyTuned = self.stations[counter]
counter +=1
print(counter, "in if")
else:
counter = 1
return "Currently Tuned: " + self.currentlyTuned
The part that i am trying to get is how do i keep the incrimination when i call seekNextStation(). at the moment it will change counter to 1 return the station in index[1] then change counter to 2, but when i call it again it will reset counter to 0 and redo the same steps
While you can rebind the index variable of the for loop, the result lasts until the start of the next iteration. Then Python rebinds it back to the next item from the sequence you passed to the for loop
It looks like you're trying to build a complicated way to cycle through stations. This type of thing is common enough to be included in the std library
>>> stations = ['station1', 'station2', 'station3', 'station4', 'station5', 'station6']
>>> from itertools import cycle
>>> station_gen = cycle(stations)
>>> next(station_gen)
'station1'
>>> next(station_gen)
'station2'
>>> next(station_gen)
'station3'
>>> next(station_gen)
'station4'
>>> next(station_gen)
'station5'
>>> next(station_gen)
'station6'
>>> next(station_gen)
'station1'
>>> next(station_gen)
'station2'
>>> next(station_gen)
'station3'
>>> next(station_gen)
'station4'
In the following code test1 works, test2 does not.
I think the copy doesn't copy to where it's supposed to.
Is this a namespace problem? Can you explain to me whats going on - or even better, how to make test 2 work (items in the must_be_sorted array, so that I can make a general purpose function)?
import copy
## test 1
items = {"gi":[{"urc":2}, {"urc":1}]}
must_be_sorted = [{"l":"gi", "key":"urc"}]
for ls in must_be_sorted:
items[ls["l"]] = sorted(items[ls["l"]], key=lambda k: k[ls["key"]])
for u in items[must_be_sorted[0]["l"]]:
print "a:", u["urc"],
print
for u in items["gi"]:
print "b:", u["urc"],
print
## test 2
items = {"gi":[{"urc":2}, {"urc":1}]}
must_be_sorted = [{"l":items["gi"], "key":"urc"}]
for ls in must_be_sorted:
#ls["l"] = sorted(ls["l"], key=lambda k: k[ls["key"]])
ls["l"] = copy.copy(sorted(ls["l"], key=lambda k: k[ls["key"]]))
for u in ls["l"]:
print "c:", u["urc"],
print
for u in items["gi"]:
print "d:", u["urc"],
'''
a: 1 a: 2
b: 1 b: 2
c: 1 c: 2
d: 2 d: 1
'''
ls["l"] and items["gi"] in test 2 point to different objects. I can use locals()["items"] to get to the same object.
I have a module with one method:
def find_inverse_matrix(C, log=False):
n = C.shape[0]
Cs = C.copy()
i = 0
C = np.matrix(np.eye(n))
B = np.matrix(np.eye(n))
J = set(range(n))
S = [0] * n
if log: print Cs
while i <= n-1:
if log: print '\nIteration', i
f = False
j = 0
ei = get_ek(i, n)
for j in J:
cj = get_ck(Cs, j)
alpha = (ei * B * cj)[0, 0]
if log: print 'alpha%s = %s' % (j, alpha)
if not(is_zero(alpha)):
f = True
break
if not(f):
exit('Inverse matrix is not exist')
J.remove(j)
S[j] = i
C[:, i] = Cs[:, j]
if log: print 'C%s:\n%s' % (i, C)
D = get_Dkz(i, B * C[:, i])
if log: print 'D%s:\n%s' % (i, D)
B = D * B
if log: print 'B%s:\n%s' % (i, B)
i += 1
if log: print '\n S = ', S
if log: print 'Result'
R = construct_matrix(B, S)
if log: print R
if log: print '\nCheck result:'
if log: print Cs * R
return R
If I call this method from this file it shows all print, but if I call if from another all print should be suppressed. Now I use check before every print, but how it do simple and pretty in 'pythonic' style?
Normally, print is a statement in the language. But if you add the line from __future__ import print_function to your imports then it is used as a function. This means two things:
a) You need to use this as a function - meaning print(Cs) instead of print Cs.
b) You can override it, since in python functions are objects you can play with.
You can define your own "my_print" functions which you can later change instead of the builtin print.
Example:
>>> from __future__ import print_function
>>> _print_ = print
>>> def myprint(*arg, **kwarg):
... _print_("yeah.")
... _print_(*arg,** kwarg)
...
>>> myprint("ok")
yeah.
ok
>>> print = myprint
>>> print('3')
yeah.
3
>>>
So just write your myprint function so that it'd check for "log" before, and your prints should be the same. Or just override print only when you don't want to suppress printing.
if __name__ == '__main__': will execute a block of code only if a file is executed directly, not loaded as a module. You can set a flag there to turn on logging.
A more pythonic way might be to pass a log function into the module instead of a flag. That way you could pass in an empty function to suppress logging.
Suppose we have a string a = "01000111000011" with n=5 "1"s. The ith "1", I would like to replace with the ith character in "ORANGE".
My result should look like:
b = "0O000RAN0000GE"
What could be the finest way to solve this problem in Python? Is it possible to bind an index to each substitution?
Many thanks!
Helga
Tons of answers/ways to do it. Mine uses a fundamental assumption that your #of 1s is equal to the length of the word you are subsituting.
a = "01000111000011"
a = a.replace("1", "%s")
b = "ORANGE"
print a % tuple(b)
Or the pythonic 1 liner ;)
print "01000111000011".replace("1", "%s") % tuple("ORANGE")
a = '01000111000011'
for char in 'ORANGE':
a = a.replace('1', char, 1)
Or:
b = iter('ORANGE')
a = ''.join(next(b) if i == '1' else i for i in '01000111000011')
Or:
import re
a = re.sub('1', lambda x, b=iter('ORANGE'): b.next(), '01000111000011')
s_iter = iter("ORANGE")
"".join(next(s_iter) if c == "1" else c for c in "01000111000011")
If the number of 1's in your source string doesn't match the length of your replacement string you can use this solution:
def helper(source, replacement):
i = 0
for c in source:
if c == '1' and i < len(replacement):
yield replacement[i]
i += 1
else:
yield c
a = '010001110001101010101'
b = 'ORANGE'
a = ''.join(helper(a, b)) # => '0O000RAN000GE01010101'
Improving on bluepnume's solution:
>>> from itertools import chain, repeat
>>> b = chain('ORANGE', repeat(None))
>>> a = ''.join((next(b) or c) if c == '1' else c for c in '010001110000110101')
>>> a
'0O000RAN0000GE0101'
[EDIT]
Or even simpler:
>>> from itertools import chain, repeat
>>> b = chain('ORANGE', repeat('1'))
>>> a = ''.join(next(b) if c == '1' else c for c in '010001110000110101')
>>> a
'0O000RAN0000GE0101'
[EDIT] #2
Also this works:
import re
>>> r = 'ORANGE'
>>> s = '010001110000110101'
>>> re.sub('1', lambda _,c=iter(r):next(c), s, len(r))
'0O000RAN0000GE0101'
Is it possible to do something like this in Python using regular expressions?
Increment every character that is a number in a string by 1
So input "123ab5" would become "234ab6"
I know I could iterate over the string and manually increment each character if it's a number, but this seems unpythonic.
note. This is not homework. I've simplified my problem down to a level that sounds like a homework exercise.
a = "123ab5"
b = ''.join(map(lambda x: str(int(x) + 1) if x.isdigit() else x, a))
or:
b = ''.join(str(int(x) + 1) if x.isdigit() else x for x in a)
or:
import string
b = a.translate(string.maketrans('0123456789', '1234567890'))
In any of these cases:
# b == "234ab6"
EDIT - the first two map 9 to a 10, the last one wraps it to 0. To wrap the first two into zero, you will have to replace str(int(x) + 1) with str((int(x) + 1) % 10)
>>> test = '123ab5'
>>> def f(x):
try:
return str(int(x)+1)
except ValueError:
return x
>>> ''.join(map(f,test))
'234ab6'
>>> a = "123ab5"
>>> def foo(n):
... try: n = int(n)+1
... except ValueError: pass
... return str(n)
...
>>> a = ''.join(map(foo, a))
>>> a
'234ab6'
by the way with a simple if or with try-catch eumiro solution with join+map is the more pythonic solution for me too