This is the normal way to write a function that takes one argument (and in this example returns its negated value):
def normal(x):
return -x
print(normal(3)) # prints -3
And here’s a way using a generator:
def send():
x = yield
while True:
x = yield -x
send = send()
next(send)
send = send.send
print(send(3)) # prints -3
And the generator way can be faster:
48.1 ± 0.2 ns send
67.7 ± 0.7 ns normal
Python: 3.13.0 (main, Nov 9 2024, 10:04:25) [GCC 14.2.1 20240910]
benchmark script
def normal(x):
return -x
print(normal(3)) # prints -3
def send():
x = yield
while True:
x = yield -x
send = send()
next(send)
send = send.send
print(send(3)) # prints -3
funcs = [normal, send]
from timeit import timeit
from statistics import mean, stdev
from itertools import repeat
from collections import deque
import sys
import random
n = 10**5
times = {f: [] for f in funcs}
def stats(f):
ts = [t * 1e9 for t in sorted(times[f])[:5]]
return f'{mean(ts):5.1f} ± {stdev(ts):3.1f} ns '
for _ in range(100):
random.shuffle(funcs)
for f in funcs:
t = timeit(lambda: deque(map(f, repeat(3, n)), 0), number=1) / n
times[f].append(t)
for f in sorted(funcs, key=stats):
print(stats(f), f.__name__)
print('\nPython:', sys.version)