[Python-Dev] Updated PEP 362 (Function Signature Object)
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