python: переопределение встроенной функции, с разными аргументами - PullRequest
0 голосов
/ 17 сентября 2018

Предисловие: вопрос в том, чтобы понять внутренности Python, поэтому, пожалуйста, не отвечайте с «обновить Python» или «импортировать шесть»

Давайте возьмем, к примеру, «печать»

Чтобы заменить встроенную функцию «print», я могу написать свою функцию python.

Python 2.6: во время выполнения я получаю синтаксическая ошибка

решение

from __future__ import print_function

Теперь я могу переопределить печать. Зачем ? Я думаю, потому что теперь мое объявление печати совпадает с новой функцией печати. ​​

Python 2.4: во время выполнения я получаю синтаксическая ошибка

Там нет

from __future__ import print_function

Итак, для print (или любой другой встроенной функции): возможно ли сделать обезьяньё исправление с новой функцией с другим объявлением - args и kwargs?


Другими словами.

from __future__ import print_function заменяет ключевое слово на функцию. Я хочу понять, КАК, в общем. Пожалуйста, не сосредотачивайтесь исключительно на print, это удобный пример.

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Все, что делает from __future__ import print_function, это переключает флаг в анализаторе, чтобы он прекратил рассматривать print как ключевое слово; Как только это будет сделано, ссылки на print станут подобными ссылкам на любое другое не ключевое слово, которое составляет допустимое имя переменной (они проходят поиск в LEGB и обнаруживаются в B LEGB, встроенной области видимости). Это поведение жестко запрограммировано глубоко в интерпретаторе Python; нет никакого способа добиться подобного эффекта для любого другого ключевого слова без создания пользовательской версии Python или участия в какой-либо другой вопиющей хакерской деятельности, выходящей далеко за рамки разумной проблемы.

Начиная с версии 2.6, __builtin__ имеет функцию print, поэтому любой модуль, который использует from __future__ import print_function (и поэтому может ссылаться на имя print в отличие от Ключевое слово print) будет видеть __builtin__.print (если оно не было скрыто чем-либо в локальной, вложенной или глобальной области видимости). Он по-прежнему там для каждого модуля, но в модулях без импорта __future__ ссылки на print преобразуются в ключевое слово во время компиляции и заменяются необработанным байт-кодом, реализующим специальный print оператор (так же, как del и return ведут себя; вы не можете назвать ни одну из этих переменных по одной и той же причине, они являются ключевыми словами), поэтому модули без импорт никогда не получит возможность поиска функции print .

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

def abs(x):
    return x  # Who needs absolute value anyway?
# From here on out, references to abs in this module see your override, not the built-in

Хотя встроенное встроенное устройство можно переназначить глобально, это ужасная идея (поскольку каждый другой модуль, использующий его, скорее всего, использует исходное поведение встроенных модулей). Тем не менее, это не сложно:

import __builtin__

def abs(x):
    return x  # Who needs absolute value anyway?

__builtin__.abs = abs
# *Every* module now sees your terrible monkeypatch, on your own head be it
0 голосов
/ 17 сентября 2018

В Python 2 print является ключевым словом. Вы не можете переопределить print по той же причине, по которой вы не можете переопределить if, while, def или любое другое ключевое слово языка; они являются частью синтаксиса языка и обрабатываются парсером, а не путем поиска функции.

from __future__ import print_function также обрабатывается парсером. Это похоже на обычный импорт, и на самом деле он импортирует вещь, но вещь, которую он импортирует, не имеет ничего общего с основной функциональностью оператора, которая заключается в том, чтобы сказать парсеру прекратить обрабатывать print как ключевое слово.

Если ключевое слово отключено, print обрабатывается как обычное имя в соответствии с обычными правилами поиска имен. Такой поиск находит встроенную функцию print, которая обычно скрывается ключевым словом.

Вы не можете определить свой собственный магический импорт; они должны быть встроены в самого переводчика. Поскольку вы не можете определить свой собственный магический импорт, и поскольку никакой другой __future__ импорт не превращает ключевые слова в не-ключевые слова, обобщение делать не нужно.

(Люди иногда говорят, что встроенные функции, такие как list или dict, являются ключевыми словами. Они не являются ключевыми словами; эти люди неправильно используют слово «ключевое слово».)


Что касается встроенных функций (не ключевых слов) с патчами для обезьян, то вы можете сделать это. Это, вероятно, плохая идея, но вы можете сделать это. Этот процесс идентичен тому, как вы обычно исправляете встроенное устройство.

...