9

So I have a function (let's call it fun1) that accepts a function as a parameter. But inside fun1, I need to access the parameter's __self__, which exists only if the function is a bound method.

The function itself must accept two str args and return a bool.

In other words, like this:

MyFuncType = Callable[[str, str], bool]

# fun1 is an unbound function
def fun1(func: MyFuncType):
    ...
    o = func.__self__
    ...
    # Some logic on the "o" object, such as logging the object's class,
    # doing some inspection, etc.
    ...

If I use MyFuncType like the above, PyCharm will complain that __self__ is not an attribute of func.

So, what type hint should I annotate func with, so that PyCharm (and possibly mypy) won't protest on that line?

(I'm using Python 3.6 by the way)

pepoluan
  • 6,132
  • 4
  • 46
  • 76
  • This may help you: https://stackoverflow.com/questions/58085648/mypy-type-annotation-for-a-bound-method. – Mario Ishac Oct 07 '20 at 16:59
  • Huh, the answer there seems to be: You can't – pepoluan Oct 07 '20 at 19:11
  • Yup sadly, but you might be able to get around it. What prevents you from taking `Callable[[, str, str], bool]`? You would need to pass `Class.method` instead of `self.method`, does your scenario allow that? Then you would declare `o` to be the first argument of that `Callable`. – Mario Ishac Oct 07 '20 at 19:17
  • The reason is to detect what object `func` was bound to and log that, plus doing some inspection on the object. So, passing a reference to an object to the func definitely won't help. Notice in the example that `fun1` was a standalone function, it has no `self` to pass to `func`. – pepoluan Oct 08 '20 at 03:44
  • I just noticed I made a typo in the sample code that might be the reason of the confusion. Fixed. Sorry about that – pepoluan Oct 08 '20 at 04:02

1 Answers1

3

Okay after some experimentation, I settle with this:

class BoundFunc:
    __self__: object

MyFuncType = Callable[[str, str], bool]
MyBoundFuncType = Union[MyFuncType, BoundFunc]

def fun1(func: MyBoundFuncType):
    ...
    o = func.__self__
    ...

This does NOT warn me if I pass an unbound function to fun1, but at least it suppresses PyCharm's warning when I try to access the __self__ property.

I figure a proper docstring on fun1 explicitly saying that func MUST be a bound method should be enough for adults...

pepoluan
  • 6,132
  • 4
  • 46
  • 76