Что более фундаментально: функции Python или объектные методы Python?

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

Например:

def fred(): pass 

Если я посмотрю на dir(fred) , я вижу, что у него есть атрибут с именем __call__ . Но dir(fred.__call__) также имеет атрибут с именем __call__ . Так делает fred.__call__.__call__ и так далее. __call__ этой цепочки объектов __call__ предполагают, что они все различны. Действительно ли они объективны или это какой-то низкоуровневый трюк переводчика?

Что более фундаментально: функции или объектные методы?

3 Solutions collect form web for “Что более фундаментально: функции Python или объектные методы Python?”

Что более фундаментально: функции или объектные методы?

Я думаю, что лучшим ответом может быть «ни». См. Часть модели выполнения в ссылке Python, где она относится к «блокам». Это то, что фактически выполняется. __call__ которую вы повесили в бесконечном поиске конца, – это просто оболочка, которая знает, как выполнить блок кода (см. Различные атрибуты func_xxx вашей функции, а фактический байт-код хранится как func_code ).

Также уместен раздел определения функций , который ссылается на «объект функции [являющийся] (обертка вокруг исполняемого кода для функции)». Наконец, есть термин, который можно назвать, что также может быть ответом на «более фундаментальный»?

Короткий ответ: оба являются фундаментальными, .__call__() для функций – это просто виртуальный трюк.


Остальная часть этого ответа немного сложна. Вы не должны это понимать, но я нахожу тему интересной. Будьте предупреждены, что я собираюсь представить серию лжи, постепенно их исправляя.

Длительный ответ

На самом фундаментальном уровне Python может иметь всего 2 операции:

  • доступ к атрибуту: obj.attr
  • вызов функции: callable(args)

obj.method(args) метода – obj.method(args) – не являются фундаментальными. Они состоят из двух шагов: выбор атрибута obj.method (который дает объект вызываемого объекта «bound method») и вызов этого с помощью args .

Другие операторы определяются в терминах них. Например, x + y пытается x.__add__(y) , возвращаясь к другим подобным комбинациям, если это не сработает.

Бесконечно длинный ответ?

Все идет нормально. Но сами вызов и атрибут доступа также определяются в терминах obj.__call__(args) и obj.__getattribute__(name) ?!?
Это черепахи до конца?!?

Фокус в том, что операции над объектом определяются вызывающими методами его типа : type(obj).__call__(obj, args) и type(obj).__getattribute__(obj, name) . Какой BTW означает, что я лгал вам, и есть третья фундаментальная операция:

  • получение типа объекта: type(obj)

Хорошо, это все равно не полезно. type(obj).__call__(...) все еще включает доступ к атрибуту и ​​вызов, поэтому это должно продолжаться до бесконечности? Втирание заключается в том, что в итоге вы нажмете встроенный тип – обычно функцию, object или type – и для них доступ к атрибутам и вызовы функций являются фундаментальными.

Поэтому, когда вы вызываете экземпляр пользовательского класса, это реализовано с помощью его метода __call__ . Но его метод __call__ вероятно, является нормальной функцией, которая может быть вызвана непосредственно. Конец тайны.

Аналогично о __getattribute__ – вы можете предоставить ему определение доступа к атрибуту для своего класса, но сам класс реализует доступ к атрибутам принципиально (если у него нет пользовательского метакласса ).

Занавес перед человеком

Итак, почему даже функция имеет метод fred.__call__ ? Ну, это просто дым и зеркала, которые Python тянет, чтобы размыть разницу между встроенными типами и пользовательскими классами. Этот метод существует для всех вызываемых объектов, но вызов нормальной функции не должен проходить через него – функции в принципе могут быть вызваны.

Точно так же все объекты имеют obj.__getattribute__ и obj.__class__ , но для встроенных типов он просто раскрывает фундаментальные операции, а не определяет его.

Мелкий шрифт

Первое утверждение о том, что Python имеет 2 фундаментальных операции, было на самом деле полной ложью. Технически все операторы Python имеют «фундаментальную» операцию на уровне C, выставленную для согласованности с помощью метода, а пользовательские классы могут переопределять эти операции с помощью аналогичных методов.

Но рассказ, который я вам сказал, может быть правдой, и это сводит вопрос к его центру: почему .__call__() и .__getattribute__() не являются бесконечной рекурсией.

Не конкретно ответ Python, но на самом низком уровне процессор понимает только действия и переменные. Из этого мы экстраполируем функции, а из переменных и функций экстраполируем объекты. Поэтому с точки зрения программирования на низком уровне я бы сказал, что более фундаментальной является функция.

Это не обязательно относится к Python в питоническом смысле и, вероятно, является хорошим примером того, почему не всегда полезно глубже вникать в реализацию языка в качестве пользователя. 🙂 Думая о функции как объекте, безусловно, лучший ответ в самом Python.

Сначала я думал, что ваши звонки отслеживаются в библиотеке Python, но метод .call имеет те же свойства, что и любой другой метод. Таким образом, он рекурсивно исследует себя, я думаю, играя с CLI python в течение нескольких минут; Я думаю, что это болезненный способ изучения архитектуры и, хотя и не обязательно ошибка, как свойство Python обрабатывает объекты под обложками. 🙂

  • Лучший способ проверить аргументы функции в Python
  • Как вы используете: isalnum, isdigit, isupper для проверки каждого символа строки?
  • Как использовать * args в функции?
  • return имя переменной извне функции, как строка внутри функции python
  • Почему это не нормально, если переменные являются глобальными, но это нормально для функций?
  • Python: Что-то делать для любого метода класса?
  • Правильное использование глобальных переменных в Python 3
  • (python) цветной печати с декоратором в функции
  •  
    Interesting Posts for Van-Lav

    Обучение навыкам нейронной сети Python

    Как комментировать / выделить 3D-график в MatPlotLib

    Канонировать экземпляр класса boto3 S3Transfer

    Множественные разделители в заголовках столбцов также разделяют значения строк

    MongoDB InvalidDocument: невозможно закодировать объект

    Получить внутренний HTML элемента в lxml

    О зрелости пижамы и зрелости GWT (с короткими мертвыми линиями) для веб-приложения

    Каков наилучший способ перевода этого рекурсивного метода python в Java?

    Python Удалить элементы массива внутри цикла

    Capture Control-C в Python

    .so не импортирует в python: динамический модуль не определяет функцию init

    Интеграция Python и C ++

    Добавьте один месяц к указанной дате (округленный день после) с помощью Python

    Использование методов класса MongoEngine Document для пользовательской проверки и предварительных сбережений

    Как использовать символическое имя группы, используя re.findall ()

    Python - лучший язык программирования в мире.