How to distinguish between a function and a class method?

前端 未结 3 885
有刺的猬
有刺的猬 2020-12-19 09:57

If a variable refers to either a function or a class method, how can I find out which one it is and get the class type in case it is a class method especially when the class

相关标签:
3条回答
  • 2020-12-19 10:36

    At the time you are calling get_info(__init__) (inside class definition) the __init__ is an ordinary function.

    def get_info(function_or_method):
        print function_or_method
    
    class Foo(object):
        def __init__(self):
            pass
        get_info(__init__)   # function
    
    def bar():
        pass
    
    get_info(Foo.__init__)   # unbound method
    get_info(Foo().__init__) # bound method
    get_info(bar)            # function
    

    Output (CPython, IronPython):

    <function __init__ at ...>
    <unbound method Foo.__init__>
    <bound method Foo.__init__ of <__main__.Foo object at ...>>
    <function bar at ...>
    

    Output (Jython):

    <function __init__ 1>
    <unbound method Foo.__init__>
    <method Foo.__init__ of Foo instance 2>
    <function bar 3>
    
    0 讨论(0)
  • 2020-12-19 10:45

    To reemphasize a point which J.F. Sebastian alluded to, I want to be able to distinguish it when the function is being declared within the class (when the type I am getting is a function and not a bound or unbound method). ie. where the first call to get_info(__init__) happens I would like to be able to detect that its a method being declared as a part of a class.

    This question came up since I am putting a decorator around it and it gets a handle to the init function and I can't actually figure out if a method is being declared within a class or as a stand alone function

    You can't. J.F. Sebastian's answer is still 100% applicable. When the body of the class definition is being executed, the class itself doesn't exist yet. The statements (the __init__ function definition, and the get_info(__init__) call) happen in a new local namespace; at the time the call to get_info occurs, __init__ is a reference to the function in that namespace, which is indistinguishable from a function defined outside of a class.

    0 讨论(0)
  • 2020-12-19 10:51

    You can distinguish between the two by checking the type:

    >>> type(bar)
    <type 'function'>
    >>> type(Foo.__init__)
    <type 'instancemethod'>
    

    or

    >>> import types
    >>> isinstance(bar, types.FunctionType)
    True
    >>> isinstance(bar, types.UnboundMethodType)
    True
    

    which is the way you'd do it in an if statement.

    Also, you can get the class from the im_class attribute of the method:

    >>> Foo.__init__.im_class
    __main__.Foo
    
    0 讨论(0)
提交回复
热议问题