[Python-Dev] Updated PEP 362 (Function Signature Object)
Nick Coghlan
ncoghlan at gmail.com
Thu Jun 7 02:12:06 CEST 2012
On Thu, Jun 7, 2012 at 8:38 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> Brett Cannon wrote:
>> This is also Python, the language that assumes everyone is an consenting
>> adult.
>
>
> Exactly, which is why I'm not asking for __signature__ to be immutable. Who
> knows, despite Larry's skepticism (and mine!), perhaps there is a use-case
> for __signature__ being modified that we haven't thought of yet.
> But that's not really the point. It may be that nobody will be stupid enough
> to mangle __signature__, and inspect.getfullargspec becomes redundant.
I've presented use cases for doing this already. Please stop calling me stupid.
It will make sense to lie in __signature__ any time there are
constraints on a callable object that aren't accurately reflected in
its Python level signature. The simplest example I can think of is a
decorator that passes extra arguments in to the underlying function on
every call. For example, here's a more elegant alternative to the
default argument hack that relies on manipulating __signature__ to
avoid breaking introspection:
def shared_vars(*shared_args):
"""Decorator factory that defines shared variables that are
passed to every invocation of the function"""
def decorator(f):
@functools.wraps(f) # Sets wrapper.__signature__ to Signature(f)
def wrapper(*args, **kwds):
full_args = shared_args + args
return f(*full_args, **kwds)
# When using this decorator, the public signature isn't
the same as that
# provided by the underlying function, as the first few positional
# arguments are provided by the decorator
sig = wrapper.__signature__
for __ in shared_args:
sig.popitem()
@shared_vars({})
def example(_state, arg1, arg2, arg3):
# _state is for private communication between "shared_vars"
and the function
# callers can't set it, and never see it (unless they dig into
example.__wrapped__)
This has always been possible, but it's been a bad idea because of the
way it breaks pydoc (including help(example)) and other automatic
documentation tools. With a writable __signature__ attribute it
becomes possible to have our cake and eat it too.
>> If people really want to keep getullargspec() around then I want to at
>> least add a note to the function that signature objects exist as an
>> alternative (but not vice-versa).
>
> +1
Also +1, since inspect.getfullargspec() and inspect.signature()
operate at different levels in order to answer different questions.
The former asks "what is the *actual* signature", while the latter
provides a way to ask "what is the *effective* signature".
That's why I see the PEP as more than just a way to more easily
introspect function signatures: the ability to set a __signature__
attribute and have the inspect module pay attention to it means it
becomes possible to cleanly advertise the signature of callables that
aren't actual functions, and *also* possible to derive a new signature
from an existing one, *without needing to care about the details of
that existing signature* (as in the example above, it's only necessary
to know how the signature will *change*).
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-Dev
mailing list