[Python-Dev] A Desperate Plea For Introspection (aka: BDFAP Needed) (original) (raw)

Guido van Rossum guido at python.org
Fri Jun 22 21🔞17 CEST 2012


On Fri, Jun 22, 2012 at 12:10 PM, Yury Selivanov <yselivanov.ml at gmail.com> wrote:

Guido,

On 2012-06-22, at 2:52 PM, Guido van Rossum wrote:

This looks great, much better than the version I reviewed half a year ago! Thanks you and others (especially Yuri) for all your efforts in guiding the discussion and implementing as the discussion went along; also thanks to Nick for participating to intensely.

Quick review notes: (1) I don't like APIs that require you to use hasattr(), which you use for returnannotation. Since you have Signature.empty to remove it, why not set it to Signature.empty when not set? Ditto for other values that are currently not set when they don't apply (Parameter.empty I think.) I think that if a function lacks an annotation, that should be reflected in the same way for its signature. Currently:  if hasattr(signature, 'returnannotation'): If we use Signature.empty:  if signature.returnannotation is not signature.empty: So (in my humble opinion) it doesn't simplify things too much.

But it is much more of a pain if someone just wants to pass the value on or print it. Instead of

print(sig.return_annotation)

you'd have to write

if hasattr(sig, 'return_annotation'): print(sig.return_annotation) else: print('empty')

In general hasattr() (or getattr() with a 3rd arg) has a code smell; making it a required part of an API truly stinks IMO.

And also you can use 'try .. except AttributeError .. else' blocks, which make code even more readable.

No, try/except blocks make code less readable.

All in all, I don't have a very strong opinion in this topic.

But I do. :-)

'empty' will also work.  When python-dev collectively decided to go with missing attributes, 'empty' didn't yet exist (we added it with 'replace()' methods).

If you think that using 'empty' is better, we can add that to the PEP.

Yes, please do.

(2) Could use an example on how to remove and add parameters using replace(). You have to build a new list of parameters and then pass it to 'replace()'. Example (from the actual signature() function implementation):  if isinstance(obj, types.MethodType):  # In this case we skip the first parameter of the underlying  # function (usually self or cls).  sig = signature(obj.func)  return sig.replace(parameters=tuple(sig.parameters.values())[1:])

(3) You are using name(arg1, *, arg2) a lot. I think in most cases you mean for arg2 to be an optional keyword arg, but this notation doesn't convey that it is optional. Can you clarify? Yes, I meant optional.  Would 'name(arg1, *, [arg2])' be better?

Hardly, because that's not valid syntax. I'd write name(arg1, *, arg2=).

(4) "If the object is a method" -- shouldn't that be "bound method"? (Unbound methods are undetectable.) Or is there some wider definition of method? What does it do for static or class methods? Yes, it should be "If the object is a bound method".  We'll fix this shortly.

Great.

classmethod as a descriptor returns a BoundMethod (bound to the class), staticmethod returns the original unmodified function, so both of them are supported automatically.

Oh, great. IIRC it wasn't always like that. Maybe just add this to the PEP as a note?

(5) Too bad there's no proposal for adding signatures to builtin functions/methods, but understood.

Of these, only (1) is a blocker for PEP acceptance -- I'd either like to see this defended vigorously (maybe it was discussed? then please quote, I can't go back and read the threads) or changed. Otherwise it looks great! --Guido Thanks!

Thank you for your hard work!

-- --Guido van Rossum (python.org/~guido)



More information about the Python-Dev mailing list