David,
I saw now that I missed the biggest problem with your proposal: yet again you
deliberately throw away errors. I'm talking about making Python code _less_
error prone, while you seem to want to make it _more_. Anyway, I'll modify your
reach() to not have the if in it that has this error hiding property, it also
simplifies it a lot. It should look like this:
def reach(name):
return inspect.stack()[-2][0].f_locals[name]
> 1. Huge performance penalty
>
> Huh? Have you actually benchmarked this is some way?! A couple lookups into
> the namespace are really not pricey operations. The cost is definitely more
> than zero, but for any function that does anything even slightly costly, the
> lookups would be barely in the noise.
I'm talking about using this for all or most function calls that aren't
positional only. So no, you can absolutely not assume I only use it to call
expensive functions. And yea, I did benchmark it, and since you didn't define
what you would think is acceptable for a benchmark you've left the door open
for me to define it. This is the result of a benchmark for 10k calls (full
source at the very end of this email):
CPython 3.6
time with use: 0:00:02.587355
time with standard kwargs: 0:00:00.003079
time with positional args: 0:00:00.003023
pypy 6.0
time with use: 0:00:01.177555
time with standard kwargs: 0:00:00.002565
time with positional args: 0:00:00.001953
So for CPython 3.6 it's 2.587355/0.003079 = 840x times slower
and pypy: 1.177555/0.002565 = 460x slower
I'm quite frankly a bit amazed pypy is so good. I was under the impression it
would be much worse there. They've clearly improved the speed of the stack
inspection since I last checked.
>
> 2. Rather verbose, so somewhat fails on the stated goal of improving
> readability
>
> The "verbose" idea I propose is 3-4 characters more, per function call, than
> your `fun(a, b, *, this, that)` proposal. It will actually be shorter than
> your newer `fun(a, b, =this, =that)` proposal once you use 4 or more keyword
> arguments.
True enough.
> 3. Tooling* falls down very hard on this
>
> It's true that tooling doesn't currently support my hypothetical function.
> It also does not support your hypothetical syntax.
If it was included in Python it would of course be added super fast, while the
use() function would not. This argument is just bogus.
> It would be *somewhat easier* to add special support for a function with a
> special name like `use()` than for new syntax. But obviously that varies by
> which tool and what purpose it is accomplishing.
Easier how? Technically? Maybe. Politically? Absolutely not. If it's in Python
then all tools _must_ follow. This solved the political problem of getting tool
support and that is the only hard one. The technical problem is a rounding
error in this situation.
> Of course, PyCharm and MyPy and PyLint aren't going to bother special casing
> a `use()` function unless or until it is widely used and/or part of the
> builtins or standard library. I don't actually advocate for such inclusion,
> but I wouldn't be stridently against that since it's just another function
> name, nothing really special.
Ah, yea, I see here you're granting my point above. Good to see we can agree on
this at least.
/ Anders
Benchmark code:
-----------------------
import inspect
from datetime import datetime
def reach(name):
return inspect.stack()[-2][0].f_locals[name]
def use(names):
kws = {}
for name in names.split():
kws[name] = reach(name)
return kws
def function(a=11, b=22, c=33, d=44):
pass
def foo():
a, b, c = 1, 2, 3
function(a=77, **use('b'))
c = 10000
start = datetime.now()
for _ in range(c):
foo()
print('time with use: %s' % (datetime.now() - start))
def bar():
a, b, c = 1, 2, 3
function(a=77, b=b)
start = datetime.now()
for _ in range(c):
bar()
print('time with standard kwargs: %s' % (datetime.now() - start))
def baz():
a, b, c = 1, 2, 3
function(77, b)
start = datetime.now()
for _ in range(c):
baz()
print('time with positional args: %s' % (datetime.now() - start))
_______________________________________________
Python-ideas mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/