2017-01-24 5 views
-2

Мы все знаем, что функции также являются объектами. Но как объектные объекты сравниваются с функциями? Каковы различия между функциональными объектами и функциями?Являются ли функции функций «Python» функциями?

По объекту функции я имею в виду г так определено:

class G(object): 
    def __call__(self, a): 
     pass 
g = G() 

По функции я имею в виду это:

def f(a): 
    pass 
+7

Что вы подразумеваете под «простыми функциями»? –

+3

Просьба привести пример, какой объект функции и функция, на ваш взгляд. –

+1

Это похоже на вопрос, в чем разница между * plain 'int' * и *' int' объектом * в Python ... там * нет простого 'int' *. –

ответ

2

Python создает функциональные объекты для вас, когда вы используете четкости заявление, или вы используете lambda expression:

>>> def foo(): pass 
... 
>>> foo 
<function foo at 0x106aafd70> 
>>> lambda: None 
<function <lambda> at 0x106d90668> 

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

+1

После того как ОП разъяснил свой вопрос, это кажется неуместным. –

+0

Объект 'function' имеет атрибут '__set__'? А как насчет атрибута '__get__'? Вы не отвечаете на мой вопрос. – jimifiki

1

TL; DR любой объект, который реализует __call__ можно назвать например: функции, пользовательские классы, и т.д ..

Чуть более длинная версия: все о е т доб)

Полный ответ на ваш вопрос о том, какая разница находится в реализации виртуальной машины python, поэтому мы должны взглянуть на python под капотом. Сначала идет концепция объекта кода. Python анализирует все, что вы бросаете на него, на свой собственный внутренний язык, который является одним и тем же на всех платформах, известных как байт-код. Очень визуальная репрезентация этого - когда вы получаете .pyc-файл после импорта пользовательской библиотеки, которую вы написали. Это необработанные инструкции для виртуальной машины python. Игнорируя, как эти инструкции создаются из вашего исходного кода, они затем выполняются PyEval_EvalFrameEx в Python/ceval.c. Исходный код немного зверя, но в конечном счете работает как простой процессор с некоторыми сложными битами, отвлеченными. Байт-код - это язык ассемблера для этого процессора. В частности, один из «опкодов» для этого «процессора» (метко назван) CALL_FUNCTION. Обратный вызов проходит через несколько вызовов, в конечном итоге доходя до PyObject_Call(). Эта функция принимает указатель на PyObject и извлекает атрибут tp_call от его типа и непосредственно называет его (технически это проверяет, если он там первый):

... 
call = func->ob_type->tp_call //func is an arg of PyObject_Call() and is a pointer to a PyObject 
... 
result = (*call)(func, arg, kw); 

Любого объект, который реализует __call__ получает атрибут tp_call с указателем к фактической функции. Я считаю, что обрабатывается slotdefs[] Difinition от объектов/typeobject.c:

FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call, 
     "__call__($self, /, *args, **kwargs)\n--\n\nCall self as a function.", 
     PyWrapperFlag_KEYWORDS) 

__call__ метод сам по себе для функций определяется в реализации CPython и определяет, как питон VM должен начать выполнение байт-код для эту функцию и как данные должны быть возвращены (если они есть). Когда вы даете произвольный класс методу __call__, атрибут представляет собой объект функции, который снова ссылается на реализацию cpython __call__. Поэтому, когда вы вызываете «нормальную» функцию, ссылается foo.__call__. когда вы вызываете класс, подлежащий вызову, self.__call__ эквивалентен foo, а фактическое ссылочное имя cpython - self.__call__.im_func.__call__.

отказ от ответственности

Это было путешествие в несколько неизведанные воды для меня, и это вполне возможно, я исказил некоторые тонкости реализации. В основном я взял от this сообщение в блоге о том, как работают python callables под капотом, а некоторые мои собственные копания через питон source code

+0

Спасибо за ваш ответ, который интересен. На самом деле я больше интересовался особенностями языка высокого уровня, например, почему объект «function» не имеет атрибутов «__set__» и «__get__». Но я нашел интересную информацию, которую вы предоставили в своем ответе. – jimifiki

+0

Функции do реализуют '__get__'. Это то, что возвращает текст« <функция A at 0x00000000064F5208> » – Aaron

+0

, гораздо чаще используют геттеры и сеттеры для применения к отдельному свойству класса, а не к самому классу. также функции не наследуются от класса базового объекта, с намерением, что если вы хотите настраивать поведение, вы можете просто реализовать его с помощью классов. технически вы могли бы создать свой собственный класс функций, но это было бы очень медленно и довольно сложно. не наследуя от базового класса объектов, python может запускать свой код c вместо этого для управления вызовом кода objec – Aaron