[Python-Dev] PEP 362 Third Revision
Yury Selivanov
yselivanov.ml at gmail.com
Thu Jun 14 15:50:38 CEST 2012
On 2012-06-14, at 8:06 AM, Victor Stinner wrote:
> Sorry if I'm asking dummy questions, I didn't follow the discussion.
>
>> * format(...) -> str
>> Formats the Signature object to a string. Optional arguments allow
>> for custom render functions for parameter names,
>> annotations and default values, along with custom separators.
>
> Hum, what are these "custom render functions"? Can you give an example?
That's how the function looks right now (I'm not sure we should load
the PEP with this):
def format(self, *, format_name=str,
format_default=repr,
format_annotation=formatannotation,
format_args=(lambda param: '*' + str(param)),
format_kwargs=(lambda param: '**' + str(param)),
token_params_separator=', ',
token_kwonly_separator='*',
token_left_paren='(',
token_right_paren=')',
token_colon=':',
token_eq='=',
token_return_annotation=' -> '):
'''Format signature to a string.
Arguments (all optional):
* format_name : A function to format names of parameters. Parameter
won't be rendered if ``None`` is returned.
* format_default : A function to format default values of parameters.
Default value won't be rendered if ``None`` is returned.
* format_annotation : A function to format parameter annotations.
Annotation won't be rendered if ``None`` is returned.
* format_args : A function to render ``*args`` like parameters.
Parameter won't be rendered if ``None`` is returned.
* format_kwargs : A function to render ``**kwargs`` like parameters.
Parameter won't be rendered if ``None`` is returned.
* token_params_separator : A separator for parameters. Set to
', ' by default.
* token_kwonly_separator : A separator for arguments and
keyword-only arguments. Defaults to '*'.
* token_left_paren : Left signature parenthesis, defaults to '('.
* token_right_paren : Left signature parenthesis, defaults to ')'.
* token_colon : Separates parameter from its annotation,
defaults to ':'.
* token_eq : Separates parameter from its default value, set to
'=' by default.
* token_return_annotation : Function return annotation, defaults
to ' -> '.
'''
I've designed it in such a way, that everything is configurable, so you
can render functions to color-term, HTML, or whatever else.
>> * is_keyword_only : bool
>> True if the parameter is keyword-only, else False.
>> * is_args : bool
>> True if the parameter accepts variable number of arguments
>> (``*args``-like), else False.
>> * is_kwargs : bool
>> True if the parameter accepts variable number of keyword
>> arguments (``**kwargs``-like), else False.
>
> Hum, why not using a attribute with a string value instead of 3
> attribute? For example:
> * argtype: "index", "varargs", "keyword" or "keyword_only"
>
> It would avoid a possible inconsitency (ex: is_args=True and
> is_kwargs=True). And it would help to implement something like a C
> switch/case using a dict: argtype => function for functions using
> signatures.
Originally, I thought the the line:
if parameters.is_args
is better looking that:
if parameters.kind == 'vararg'
But, I like your arguments regarding inconsistency and dispatch
through a dict (someone may find it useful). Also, Larry gave
another one - who knows if we add another type of arguments in
the future.
I guess if nobody really wants to keep 'is_args', we can alter the
PEP.
Let's consider replacement of 'Parameter.is_*' set of attributes with
a single 'Parameter.kind' attribute, which will have the following
possible values: 'positional', 'vararg', 'keyword-only', 'varkwarg'.
(I think 'positional' is more intuitive than 'index'?)
>> * is_implemented : bool
>> True if the parameter is implemented for use. Some platforms
>> implement functions but can't support specific parameters
>> (e.g. "mode" for ``os.mkdir``). Passing in an unimplemented
>> parameter may result in the parameter being ignored,
>> or in NotImplementedError being raised. It is intended that
>> all conditions where ``is_implemented`` may be False be
>> thoroughly documented.
>
> I suppose that the value depends on the running platform? (For
> example, you may get a different value on Linux and Windows.)
Correct.
>> Implementation
>> ==============
>>
>> - If the object has a ``__signature__`` attribute and if it
>> is not ``None`` - return a deepcopy of it
>
> Oh, why copying the object? It may impact performances. If fhe caller
> knows that it will modify the signature, it can deepcopy the
> signature.
There was a discussion on this topic earlier on python-dev.
In short - as we usually create new signatures with each 'signature()'
call, users will expect that they can modify those freely. But if we
have one defined in __signature__, without copying it, all its
modifications will be persistent across 'signature()' calls. So the
deepcopy here is required more for the consistency reasons. Besides,
I don't think that 'signature()' will be used extensively in
performance-critical types of code. And even if it is - you can just
cache it manually.
>> - If it is ``None`` and the object is an instance of
>> ``BuiltinFunction``, raise a ``ValueError``
>
> What about builtin functions (ex: len)? Do you plan to add a
> __signature__ attribute? If yes, something created on demand or
> created at startup?
Larry is going to add signatures to some 'os' module functions. But
that would it for 3.3, I guess.
> It would be nice to have a C API to create Signature objects, maybe
> from the same format string than PyArg_Parse*() functions. But it can
> be implemented later.
Then parameters will lack the 'name' attribute. I think we need another
approach here.
> Is it possible to build a Signature object from a string describing
> the prototype (ex: "def f(x, y): pass")? (I mean: do you plan to add
> such function?)
There are no plans to add it now (no good reasons to include such
functionality in 3.3 at least)
Thank you,
-
Yury
More information about the Python-Dev
mailing list