On Wed, Mar 04, 2020 at 12:19:25PM +0200, Alex Hall wrote:
> Can you explain where `except ParameterError` would produce better code
> than the best current alternative?
Serhiy came up with a good use-case that I hadn't considered: functions
which take arbitrary callback functions as argument, e.g. sorted() with
a key function.
Both of these calls raise TypeError, but for different reasons:
# right number of arguments passed to the key function,
# but the wrong argument type
sorted([3, 5, 1], key=len)
# wrong number of arguments passed to the key function
sorted([3, 5, 1], key=isinstance)
It might be useful to be able to distinguish the two cases.
My earlier use-case still stands: feature detection where a function has
changed its parameter list. More on this below.
> It seems to me that using this is like
> stating "this code might be wrong" and would generally produce bad code.
It seems to me that your comment above could be equally said about *any*
use of exceptions: "this code might be wrong, so we'll stick it in a
try...except block". Only that's not how most of us actually use
exceptions.
> For example if I wanted to use math.gcd on multiple values but I need to
> support Python versions that only allow two arguments, then I'll just apply
> it to two arguments at a time, maybe with functools.reduce.
I've done that myself. Not specifically with gcd, but with other
functions, which I don't remember off the top of my head.
gcd is a particularly simple example because it is so easy to wrap.
Excluding function header and docstring, the code is just six lines:
if len(args) == 0:
return 1
elif len(args) == 1:
return abs(args[0])
else:
return reduce(_gcd, args)
Not all cases will be that simple, or they may involve a serious
performance cost. In general, the official version is going to be
faster and better tested than the wrapper version.
Why shouldn't I use the fast, well-tested standard version if it is
available? I just need a reliable way to detect the needed feature.
This is not specifically about gcd. It could be about functions of
arbitrary complexity:
try:
# Test whether the aardvark function supports a
# `hovercraft` parameter.
result = aardvark(
spam, eggs, cheese, hovercraft=1
)
except ParameterError:
# No hovercraft parameter allowed, create a wrapper.
...
TypeError is less satisfactory because I cannot easily distinguish the
two cases:
1. The 'hovercraft' parameter is not available;
2. The 'hovercraft' parameter is available, but I have made some other
error in the function call which results in a TypeError.
> And in general
> if I want to distinguish between versions I'd much rather just check the
> version and thus assert "this code is correct for this version".
Feature detection is more reliable.
What if the caller of my library has back-ported the new, advanced
version of aardvark() to their Python? Instead of using the faster,
better tested official backport, my code will use my wrapper.
What if the caller is using my library with another interpreter, say
PyPy or Jython, which doesn't support the feature I need? With feature
detection, my code will simply fall back to the wrapper. With version
checking, it will wrongly assert the feature is available, and then
crash later.
As far as I can tell, feature detection has more or less completely
overshadowed version checks in the browser and Javascript space. In my
opinion, checking the version should only be used when it is too hard to
detect the feature.
> If you catch ParameterError, how do you know that it came directly from the
> line you caught it from and not deeper within?
Does it matter?
If the call aardvark(*args, hovercraft=1) leaks a ParameterError from
deep inside its internals, then even if the feature is technically
available according to a version check, it is too buggy to use and I
need to use my wrapper.
> If you want to check that you're passing parameters properly, I suggest
> writing code like this:
>
> import inspect
>
> signature = inspect.signature(func)
And what if the function I'm checking doesn't support signature
metadata?
https://docs.python.org/3/library/inspect.html#inspect.signature
I can wrap the call to signature() in try...except, but what's my
fallback if I can't check the signature?
py> inspect.signature(math.gcd)
Traceback (most recent call last):
[...]
TypeError: 'feature_version' is an invalid keyword argument
for compile()
--
Steven
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/7SXIB2W7PJGWAM72MOXBWMI5G6OXKAMG/
Code of Conduct: http://python.org/psf/codeofconduct/