[Python-Dev] Updated PEP 362 (Function Signature Object) (original) (raw)

Steven D'Aprano steve at pearwood.info
Fri Jun 8 04:08:09 CEST 2012


Nick Coghlan wrote:

On Fri, Jun 8, 2012 at 4:34 AM, Larry Hastings <larry at hastings.org> wrote:

In other words: this is possible but extremely unlikely, and will only be done knowingly and with deliberate intent by a skilled practitioner.

I think it's reasonable to declare that, if you're monkeying around with dunder attributes on a function, it's up to you to clear the f.signature cache if it's set. Like Spiderman's uncle Cliff Robertson said: with great power comes great responsibility. I am now firmly in the "using signature as a cache is fine, don't make copies for no reason" camp. I have a simpler rule: functions in the inspect module should not have side effects on the objects they're used to inspect. When I call "inspect.signature(f)", I expect to get something I can modify without affecting the state of "f". That means, even if f.signature is set, the signature function will need to return a copy rather than a direct reference to the original. If f.signature is going to be copied anyway, then there's no reason to cache it, unless we want to say something other than what the inspect module would automatically derive from other attributes like func, wrapped, call, code, closure, etc.

There is still a potential reason to cache func.signature: it's a relatively large chunk of fields, which duplicates a lot of already existing data. Why make all function objects bigger when only a small minority will be inspected for their signature?

I think that lazy evaluation of signature is desirable, and caching it is certainly desirable now that you have convinced me that there are use-cases for setting signature.

Perhaps func.signature should be a computed the first time it is accessed? Something conceptually like this:

class FunctionWithSignature(types.FunctionType): @property def signature(self): if hasattr(self._sig): return self._sig sig = self._get_signature() # Left as an exercise for the reader. self._sig = sig return sig @signature.setter def signature(self, sig): self._sig = sig @signature.deleter def signature(self): del self._sig

-- Steven



More information about the Python-Dev mailing list