[Python-Dev] PEP 362 minor nits

Yury Selivanov yselivanov.ml at gmail.com
Tue Jun 19 20:10:23 CEST 2012


On 2012-06-19, at 12:33 PM, Jim Jewett wrote:

> 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}

The first one (ba.args == (1,))

> Does it matter how the argument was bound?  As in, would
> 
>>>> ba2=s.bind(a=2)
> 
> produce a different answer?

No.

> 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

Right (there was a bug in BoundArguments.args & kwargs - fixed and
unit-tested now)

> 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.

OK, so do you want to elaborate on BoundArguments.args & kwargs?
(I think it's fine now)

...

>>>   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.

I can tweak the PEP to make it more clear for those who don't know
that staticmethods are not exactly methods, but do we really need that?
(I don't want to change the implementation, because every 'isinstance'
call matters, and we need to check on 'types.FunctionType' as soon as
possible)

>>>   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.

Got it.  I currently check the MRO in the implementation, so your
example will work as expected - B will have a signature of A.__init__

I'll update the PEP wording.

-
Yury


More information about the Python-Dev mailing list