Как отличить функцию от метода класса? - PullRequest
6 голосов
/ 30 марта 2009

Если переменная ссылается либо на функцию, либо на метод класса, как я могу узнать, какой это тип, и получить тип класса в случае, если это метод класса, особенно когда класс все еще объявляется, как в данном примере .

например.

def get_info(function_or_method):
    print function_or_method

class Foo(object):
    def __init__(self):
        pass

    get_info(__init__)

def bar():
    pass

get_info(bar)

Обновление на вопрос после первых двух ответов Дэвида и Дж. Ф. Себастьяна Чтобы еще раз подчеркнуть точку, на которую ссылался Дж. Ф. Себастьян, я хочу иметь возможность различить ее, когда функция объявляется в классе (когда тип, который я получаю, является функцией, а не связанным или несвязанным методом). то есть. где происходит первый вызов get_info(__init__), я хотел бы иметь возможность обнаружить, что это метод, объявленный как часть класса.

Этот вопрос возник, так как я помещаю декоратор вокруг него, и он получает дескриптор функции init , и я не могу понять, объявлен ли метод в классе или как автономная функция

Ответы [ 3 ]

12 голосов
/ 30 марта 2009

Вы можете различить два, проверив тип:

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

или

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

именно так вы и поступите в выражении if.

Кроме того, вы можете получить класс из атрибута im_class метода:

>>> Foo.__init__.im_class
__main__.Foo
9 голосов
/ 30 марта 2009

Во время вызова get_info(__init__) (внутри определения класса) __init__ - это обычная функция.

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

Вывод (CPython, IronPython):

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

Выход (Jython):

<function __init__ 1>
<unbound method Foo.__init__>
<method Foo.__init__ of Foo instance 2>
<function bar 3>
4 голосов
/ 30 марта 2009

Чтобы еще раз подчеркнуть точку, на которую ссылался Дж. Ф. Себастьян, я хочу иметь возможность различить ее, когда функция объявляется в классе (когда тип, который я получаю, является функцией, а не связанным или несвязанным методом). то есть. где происходит первый вызов get_info(__init__), я хотел бы иметь возможность обнаружить, что его метод объявлен как часть класса.

Этот вопрос возник, так как я помещаю декоратор вокруг него, и он получает дескриптор функции init, и я не могу понять, объявлен ли метод в классе или как отдельная функция

Ты не можешь. Ответ Дж. Ф. Себастьяна все еще применим на 100%. Когда выполняется тело определения класса, сам класс еще не существует. Операторы (определение функции __init__ и вызов get_info(__init__)) происходят в новом локальном пространстве имен; в то время, когда происходит вызов get_info, __init__ является ссылкой на функцию в этом пространстве имен, которая неотличима от функции, определенной вне класса.

...