Nick Coghlan wrote:
On Fri, Jun 8, 2012 at 4:34 AM, Larry Hastings <la...@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

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to