how to inspect if something includes a bound first param
inspect.getargspec(method) and inspect.signature(method) both include the 'self' parameter but how are we to figure out from method itself that it is actually bound and that its first parameter is expected to be a bound instance? So far I've come up with: *inspect.ismethod(method) or inspect.ismethoddescriptor(method)* But that is still not quite right as it remains False in 3.4 for the simple case of:
class A: ... def x(self): ... pass ... inspect.ismethod(A.x) False inspect.ismethoddescriptor(A.x) False inspect.signature(A.x).parameters mappingproxy(OrderedDict([('self', <Parameter at 0x7fdd8188eae8 'self'>)])) inspect.getargspec(A.x) ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
The above works if use it on object.__init__, but not on a method of an uninstantiated class. (it also works on the instantiated A().x) Checking if *(inspect.isfunction(method) and method.__qualname__ != method.__name__)* perhaps but that seems questionably hacky. Is there a right way to do this via the inspect module that I've missed? It seems like that'd be nice, but I don't feel like I know enough to write up a feature request for it yet. (granted I hope nobody *wants* to write code that does this...) -gps
On 2/24/2015 8:56 PM, Gregory P. Smith wrote:
inspect.getargspec(method) and inspect.signature(method) both include the 'self' parameter but how are we to figure out from method itself that it is actually bound and that its first parameter is expected to be a bound instance?
So far I've come up with: /inspect.ismethod(method) or inspect.ismethoddescriptor(method)/
But that is still not quite right as it remains False in 3.4 for the simple case of:
class A: ... def x(self): ... pass ... inspect.ismethod(A.x) False inspect.ismethoddescriptor(A.x) False inspect.signature(A.x).parameters mappingproxy(OrderedDict([('self', <Parameter at 0x7fdd8188eae8 'self'>)])) inspect.getargspec(A.x) ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
The above works if use it on object.__init__, but not on a method of an uninstantiated class. (it also works on the instantiated A().x)
Checking if /(inspect.isfunction(method) and method.__qualname__ != method.__name__)/ perhaps but that seems questionably hacky. Is there a right way to do this via the inspect module that I've missed?
It seems like that'd be nice, but I don't feel like I know enough to write up a feature request for it yet. (granted I hope nobody /wants/ to write code that does this...)
I'm not sure if it's correct, but deep in a library of mine I have: elif type(fn) == types.MethodType: # bound method? if fn.im_self is None: # no 'self' nskip = 0 else: # need to supply 'self' nskip = 1 This is also a 2.x library. No idea if it works with 3.x. Eric.
On 2/24/2015 9:02 PM, Eric V. Smith wrote:
I'm not sure if it's correct, but deep in a library of mine I have:
elif type(fn) == types.MethodType: # bound method? if fn.im_self is None: # no 'self' nskip = 0 else: # need to supply 'self' nskip = 1
This is also a 2.x library. No idea if it works with 3.x.
It will not. 3.x does not have 'unbound methods' in the above sense, and for bound methods, fn.im_self is now fn.__self__. -- Terry Jan Reedy
On 2/24/2015 8:56 PM, Gregory P. Smith wrote:
inspect.getargspec(method) and inspect.signature(method) both include the 'self' parameter but how are we to figure out from method itself that it is actually bound and that its first parameter is expected to be a bound instance?
This seems like a python-list question.
So far I've come up with: /inspect.ismethod(method) or inspect.ismethoddescriptor(method)/
But that is still not quite right as it remains False in 3.4 for the simple case of:
class A: ... def x(self): ... pass ... inspect.ismethod(A.x) False inspect.ismethoddescriptor(A.x) False
These are correct. A.x is the function resulting from execution of the def statement.
type(A.x) <class 'function'>
This is different from 2.x. If you call the function as a function, there is no requirement on its argument, and no binding.
A.x(3) # returns None
-- Terry Jan Reedy
On 02/24/2015 05:56 PM, Gregory P. Smith wrote:
inspect.getargspec(method) and inspect.signature(method) both include the 'self' parameter but how are we to figure out from method itself that it is actually bound and that its first parameter is expected to be a bound instance?
Given the mechanisms involved, surely this question is a bit nonsensical? The function doesn't "expect" anything, it's just a function. (I remind you, Python 3 dropped the whole concept of an "unbound method".) If it happens to live inside a class, and it's accessed through an instance of the class, then the first parameter gets bound. Consider: >>> class A: ... def x(self, a): print(a) ... >>> a = A() inspect.signature(A.x).parameters has two parameters, "self" and "a". inspect.signature(a.x).parameters has only one parameter, "a". I claiim this is what you want. It's analagous to a functools.partial object. It would be awfully confusing if the signature of a functools.partial object include the parameters handled by the partial object. IMO inspect.getargspec and inspect.getfullargspec get this wrong; for a.x they include the "self" parameter. If you were constructing a call to this function dynamically you'd include one too many parameters. //arry/
participants (4)
-
Eric V. Smith
-
Gregory P. Smith
-
Larry Hastings
-
Terry Reedy