What Is The Best Way To Share A Value By All The Generators Created By A Function?
Solution 1:
This has been asked many times in many forms. Read any number of other questions about mutable default arguments and the new Python 3 nonlocal
keyword. On Python 2, you could use a function attribute:
defsentinel(fillvalue = fillvalue):
defret():
sentinel.counter += 1if sentinel.counter == len(args):
raise LongestExhausted
yield fillvalue
return ret()
sentinel.counter = 0
or use global
both inside ret
and inside izip_longest
so you're always referencing a global variable:
global counter
counter = 0defsentinel(fillvalue = fillvalue):
defret():
global counter
counter += 1if counter == len(args):
raise LongestExhausted
yield fillvalue
return ret()
However, using global
restricts you to only one izip_longest
at a time -- see the comments on the other answer.
You're also defining a new ret
every time sentinel
is called (once per iterator) -- you could instead do something like
global counter
counter = 0
arglen = len(args)
def ret():
global counter
counter += 1if counter == arglen:
raise LongestExhausted
return fillvalue
def sentinel():
yieldret()
Example code for having sentinel
outside izip_longest
in re your question from the comments:
defsentinel(counter, arglen, fillvalue):
defret():
counter[0] += 1if counter[0] == arglen:
raise LongestExhausted
yield fillvalue
return ret()
defizip_longest_modified_my(*args, **kwds):
# izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
fillvalue = kwds.get('fillvalue')
classLongestExhausted(Exception):
pass
fillers = repeat(fillvalue)
counter = [0]
arglen = len(args)
iters = [chain(it, sentinel(counter, arglen, fillvalue), fillers) for it in args]
try:
for tup in izip(*iters):
yield tup
except LongestExhausted:
pass
Here you're again using a list just as a container to get around the problems accessing outer scopes in Python 2.
Solution 2:
Using a global is a bad idea, IMHO. You need to make sure to reset the counter properly between calls. But more seriously this is a generator; you don't even need threading to have multiple calls to a generator in flight at the same time, which will wreck havoc with any attempt to sanely use a global to keep track of state.
You could just explicitly pass a reference to a mutable object into sentinel, and then into ret. It looks like your code controls all the calls to them. Function parameters are the original and boring way of transferring references between scopes!
Post a Comment for "What Is The Best Way To Share A Value By All The Generators Created By A Function?"