[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