Développeur chez
Travaille avec Python depuis 2013
A mis du temps à comprendre
les générateurs
for item in iterable:
do_something(item)
iterator = iter(iterable)
while True:
try:
item = next(iterator)
except StopIteration:
break
do_something(item)
Renvoie un itérateur de générateur
Objet correspondant au flux des données
()
<generator>
def validate(form):
if form.password_1 != form.password_2:
yield "password-match-error"
if len(form.password_1) < 8:
yield "password-too-short"
if form.password_1 == "password123":
raise StopIteration("please-no")
errors = []
validator = validate(form=form)
for message in validator:
errors.append(error)
errors = (
message
for message in validate(form)
)
errors = (
message
for message in validate(form)
)
errors = tuple(
message
for message in validate(form)
)
errors = [
message
for message in validate(form)
]
Générateur
Tuple
Liste
one_line_gen = (x for x in range(3))
for x in one_line_gen:
print(x)
for x in one_line_gen:
print(x) # jamais exécuté !
Debugger quantique ?
#yolo
def iters(numbers, values):
iterators = []
for value in values:
iterators.append(n
for n in numbers
if n == value)
return iterators
iters([1, 2, 3], [1, 4, 3])
[[1], [], [3]] # Attendu
[[3], [3], [3]] # Reçu
def iters2(numbers, values):
def build_gen(value):
return (n
for n in numbers
if n == value)
return [build_gen(value)
for value in values]
def follow(infile):
# On se place à la fin du fichier
infile.seek(0, os.SEEK_END)
while True:
line = infile.readline()
if not line:
# On attend un peu
time.sleep(0.1)
continue
yield line
for line in follow(logfile):
print(line)
def wrapper(logfile):
...
for line in follow(logfile):
yield line
def better_wrapper(logfile):
yield from follow(infile)
yield from
_i = iter(EXPR)
try:
_y = next(_i)
except StopIteration as _e:
_r = _e.value
else:
while 1:
try:
_s = yield _y
except GeneratorExit as _e:
try:
_m = _i.close
except AttributeError:
pass
else:
_m()
raise _e
except BaseException as _e:
_x = sys.exc_info()
try:
_m = _i.throw
except AttributeError:
raise _e
else:
try:
_y = _m(*_x)
except StopIteration as _e:
_r = _e.value
break
else:
try:
if _s is None:
_y = next(_i)
else:
_y = _i.send(_s)
except StopIteration as _e:
_r = _e.value
break
RESULT = _r
yield from
RESULT = yield from EXPR
vs
TypeError: can't send non-None value to a just-started generator
def grep(pattern):
while True:
line = yield
if pattern in line:
print(line)
g = grep("Python")
next(g)
g.send("Coucou le meetup Python !")
g.send("Rien à voir ici")
g.send("Python c'est cool, non ?")
def coroutine(func):
def start(*args,**kwargs):
cr = func(*args,**kwargs)
next(cr)
return cr
return start
Un petit décorateur bien pratique
@coroutine
def grep(pattern):
...
g = grep("Python")
g.send("Coucou le meetup Python !")
g.send("Rien à voir ici")
g.send("Python c'est cool, non ?")
@coroutine
def func():
output = None
while True:
input_ = yield output
output = compute(input_)
f = func()
print(f.send("something"))
print(f.send("else"))
"C'est une révolution" - Steve Jobs, peut-être
@coroutine
def grep(pattern, target):
while True:
line = yield
if pattern in line:
target.send(line)
@coroutine
def logger(color):
while True:
line = yield
echo(line, color)
g = grep('Python', logger('red'))
g.send("Python")
g.send("PHP !")
(the good parts)
function* gen() {
yield 1;
yield 2;
yield 3;
}
const g = gen()
function* func1() {
yield 42;
}
function* func2() {
yield* func1();
}
A
B
C
D
E
Transaction
function* fetchUserSaga(action) {
try {
const user = yield call(
Api.fetchUser,
action.userId)
yield put(userFetchSucceeded(user))
} catch (e) {
yield put(userFetchFailed(e.message))
}
}
function* mySaga() {
yield take("USER_FETCH_REQUESTED",
fetchUserSaga);
}
En gros
(très)