How to detect the usage of an unbound method in Python 3.x?

I have a library that can take either a class function or a normal function with certain signatures. A class normally looks like this:

class MyObject(object):
    def __init__(self, request):
       self.request = request

    def run(self):
        return 'OK'

and the function format is this:

def my_func(request):
    retrn 'OK'

The usage of this is:

add_runner(MyObject, attr='run')
add_runner(my_func)

but sometimes people utilize this wrong and pass the class function to my library:

add_runner(MyObject.run)

I have detected this in Python 2.x as an unbound method and raise an error to alert them that they are using my API wrong but in Python 3.x I can't find any way to actually detect they are doing this wrong. What am I missing?

I think this works well, I just hate that I have to detect self

def _is_unbound(fn):
    """
    This consistently verifies that the callable is bound to a
    class.
    """
    spec = inspect.getargspec(fn)
    has_self = len(spec.args) > 0 and spec.args[0] == 'self'
    is_bound = getattr(fn, im_self, None) is not None

    if not is_bound:
        if PY3 and inspect.isfunction(fn) and has_self:
            return True
        elif inspect.ismethod(fn):
            return True

    return False

Bound, unbound, and static methods in Python, For example, if there is a class “Fruits”, and instances like apple, orange As of Python 3.0, the unbound methods have been removed from the� The idea of bound and unbound methods was removed in Python 3. In Python 3 when you declare a method within a class, you are using a def keyword, thus creating a function object. This is a regular function, and the surrounding class works as its namespace. In the following example we declare method f within class A, and it becomes a function A.f:

With python 3, unbounded methods are exactly equivalent to functions ( see discussion in Get defining class of unbound method object in Python 3 )

Checking the first argument name == 'self' can be problematic, since there is no requirement for the first argument of a method to be 'self'. Any valid argument name could be used (e.g., 'myself', 'this', etc).

I would suggest that use continue to use the argument inspection, to ensure that the caller has provided a function with call signature that you expect.

In python3 it is possible for the unbound method to properly be passed to add_runner:

class AnotherObject:
   def run(request):
     return "OK"

add_runner(AnotherObject.run)

[Tutor] Unbound Method Error, The same mechanism is used for methods: the method object just object like this: type(instance).method(instance, x, y, z) Some people find it hard to If you call it via the instance, you get a bound method and self if 2) What changes between 3.1.3 and 2.6.6 that makes this section of code not > work? python,python-3.x,pyqt,pyqt4. I think the problem is with your start.py file. You have a function refreshgui which re imports start.py import will run every part of the code in the file. It is customary to wrap the main functionality in an ''if __name__ == '__main__': to prevent code from being run on

If you can assume Py27 and later, it seems like the following would work:

def is_bound(method):
    return bool(getattr(method, '__self__', None))

In Py26, the __self__ attribute was added in addition to im_self for fowards compatibility with Py3 (see the documentation for details).

In Py2, an unbound method will have a __self__ but the value will be None. A bound method will have a __self__ that corresponds to the instance of the class where it was called.

In Py3, a "bound" method (one called on an instance of a class) will define __self__. In contrast, an "unbound" method (one called on the class definition itself) will not define __self__.

Descriptor HowTo Guide — Python 2.7.18 documentation, Descriptors are a powerful, general purpose protocol. Define any of these methods and an object is considered a Properties, bound and unbound methods, static methods, and class print E.f(3) 3 >>> print E().f(3) 3. When invoked on a ~100MB XML file, the peak memory usage of the Python process running this script is ~560MB and it takes 2.9 seconds to run. Note that we don't really need the whole tree in memory for this task. It would suffice to just detect location elements with the desired value. All the other data can be discarded.

Other Core Object Changes — Conservative Python 3 Porting Guide , This page details miscellaneous changes to core objects: functions and classes. Python 3 removes the old names for these attributes: new ones. However, it does not check that the attribute is retreived from a function object. If your code uses the func_* names for other purposes, you'll need to revert the fixer's changes. Stack Overflow | The World’s Largest Online Community for Developers

Python 3 fact: Unbound methods are no more : Python, That means in Python3, you don't need to use the @staticmethod decorator for class that in Python 3, Class.method is a function, and not an unbound method. I'm sadly finding r/learnpython to be more interesting than r/Python and am� TutorialsTeacher.com is optimized for learning web technologies step by step. Examples might be simplified to improve reading and basic understanding.

Unbound Methods, A method can have a special Python-defined name with two leading and two trailing underscores. Python Thus, to define a class without base classes, use a statement such as: 5.1.3.2 Attributes of instance objects When these two lookup procedures do not find an attribute, Python raises an AttributeError exception. Stack Overflow | The World’s Largest Online Community for Developers

Comments
  • Yes, but what I want to detect is invalid usage. So if run is an instance method (i.e tied to an instance of the class via self) then it is invalid because I don't want a self to pass it
  • In the case that run is an instance method, inspect.ismethod(objectInstance.run) would return True