[Python-Dev] PEP 362 minor nits

Jim Jewett jimjjewett at gmail.com
Tue Jun 19 18:33:52 CEST 2012


On Tue, Jun 19, 2012 at 11:53 AM, Yury Selivanov
<yselivanov.ml at gmail.com> wrote:

>> Based on:  http://hg.python.org/peps/file/tip/pep-0362.txt
>> view pep-0362.txt @ 4466:659639095ace
>> ==================

>>   142 * args : tuple
>>   143     Tuple of positional arguments values.  Dynamically computed from
>>   144     the 'arguments' attribute.
>>   145 * kwargs : dict
>>   146     Dict of keyword arguments values. Dynamically computed from
>>   147     the 'arguments' attribute.

>> Do you want to specify which will contain the normal parameters, that
>> could be called either way?  My naive assumption would be that as much
>> as possible gets shoved into args, but once a positional parameter is
>> left to default, remaining parameters are stuck in kwargs.

> Correct, we push as much as possible to 'args'.  Only var_keyword
> and keyword_only args go to 'kwargs'.

> But the words "positional" and "keyword" more refer to what particularly
> *args and  **kwargs do, disconnected from the Signature's parameters.

Which is why there is some ambiguity, and I wondered if you were
intentionally leaving it open or not.

    >>> def f(a): pass
    >>> s=signature(f)

    >>> ba1=s.bind(1)

Now which of the following are true?

    >>> # Ambiguous parameters to args
    >>> ba.args==(1,)  and ba.kwargs=={}

    >>> # or ambiguous parameters to kwargs
    >>> ba.args=() and ba.kwargs={a:1}

Does it matter how the argument was bound?  As in, would

    >>> ba2=s.bind(a=2)

produce a different answer?



If as much as possible goes to args, then:

    >>> def g(a=1, b=2, c=3): pass
    >>> s=signature(g)
    >>> ba=s.bind(a=10, c=13)

would imply

    >>> ba.args == (10,) and ba.kwargs={c:13}
    True

because a can be written positionally, but c can't unless b is, and b
shouldn't be because it relied on the default value.


>>   172     - If the object is not callable - raise a TypeError
>>   173
>>   174     - If the object has a ``__signature__`` attribute and if it
>>   175       is not ``None`` - return a shallow copy of it

>> Should these two be reversed?

> Do you have a use-case?

Not really; the only cases that come to mind are cases where it makes
sense to look at an explicit signature attribute, instead of calling
the factory.


>>   183     - If the object is a method or a classmethod, construct and return
>>   184       a new ``Signature`` object, with its first parameter (usually
>>   185       ``self`` or ``cls``) removed
>>
>>   187     - If the object is a staticmethod, construct and return
>>   188       a new ``Signature`` object

>> I would reverse these two, to make it clear that a staticmethod is not
>> treated as a method.

> It's actually not how it's implemented.
...
> But that's an implementation detail, the algorithm in the PEP just
> shows the big picture (is it OK?).

Right; implementing it in the other order is fine, so long as the
actual tests for methods exclude staticmethods.  But for someone
trying to understand it, staticmethods sound like a kind of method,
and I would expect them to be included in something that handles
methods, unless they were already excluded by a prior clause.

>>   194     - If the object is a class or metaclass:
>>   195
>>   196         - If the object's type has a ``__call__`` method defined in
>>   197           its MRO, return a Signature for it
>>   198
>>   199         - If the object has a ``__new__`` method defined in its class,
>>   200           return a Signature object for it
>>   201
>>   202         - If the object has a ``__init__`` method defined in its class,
>>   203           return a Signature object for it
>>
>> What happens if it inherits a __new__ or __init__ from something more
>> derived than object?

> What do you mean by "more derived than object"?

    >>> class A:
                def __init__(self): pass
    >>> class B(A): ...

Because of the distinction between "in its MRO" and "in its class", it
looks like the signature of A is based on its __init__, but the
signature of subclass B is not.

-jJ


More information about the Python-Dev mailing list