В последнее время я изучал Python и удивляюсь его превосходным возможностям метапрограммирования во время выполнения. Раньше я сталкивался с термином "метапрограммирование времени выполнения", когда я читал о Smalltalk, который, насколько мне известно, обладает лучшими возможностями метапрограммирования во время выполнения. Насколько хорошо Python складывается против Smalltalk w.r.t. метапрограммированием? Каковы заметные различия между подходами, взятыми на двух языках?
Сравнение возможностей Python и Smalltalk - Metaprogramming
Ответ 1
Python на самом деле достаточно хорош здесь. Smalltalk обычно не делает явного различия между программой и метапрограммой, но Python является более явным - например, особый синтаксис для декораторов или соглашение об именах __foo__()
для метапрограммирующих крючков. Это хорошая вещь.
С другой стороны, это немного сравнение яблок с апельсинами. Smalltalk - это меньший, более жесткий язык, чем Python, и поэтому есть меньше материалов для манипуляции с метапрограммами. Например, рассмотрим __getattr__()
. Это крючок, который позволяет объектам Python предоставлять настраиваемую реализацию доступа к атрибутам. У Smalltalk нет ничего подобного. Но! Smalltalk обеспечивает более жесткую инкапсуляцию внутреннего состояния объекта, и нет эквивалента синтаксиса object.attribute
, который используется в Python. Таким образом, чтение состояния объекта требует прохождения метода... что именно предоставляет __getattr__()
. Поэтому для многих случаев, когда вы использовали бы __getattr__()
в Python, вы просто напишете обычный метод в Smalltalk - не требуется метапрограммирование.
И это так повсюду: Python __getitem__()
и друзья позволяют писать классы, имитирующие списки или словари. Smalltalk не нуждается в этом, потому что Array и Dictionary являются обычными классами Smalltalk и специального синтаксиса для их использования нет. Python __eq__()
и т.д. Позволяют перегрузить оператор. У Smalltalk нет операторов, поэтому вы можете реализовать +
, не делая ничего особенного. Python contextlib предоставляет отличные инструменты для реализации ваших собственных менеджеров контекста. У Smalltalk нет конструкции with
, но у нее действительно легкий синтаксис для lambdas, который позволяет вам делать то же самое прямолинейно.
Средство метапрограммирования Smalltalk имеет тенденцию быть довольно низким. Вы можете, например, создать свои собственные экземпляры CompiledMethod
и вставить их в словарь методов класса. Вы также можете написать свой собственный компилятор и указать, что с ним будут скомпилированы все методы определенного класса. Это позволяет использовать всевозможные вещи - я видел проекты, которые экспериментируют с альтернативными синтаксисами, байт-код инструмента для профилирования, ловушки читает и записывает в переменные экземпляра для прозрачной настойчивости и т.д.
Возможности метапрограммирования Smalltalk являются мощными, но они не так аккуратно организованы, как Python, и не используются так часто.
Ответ 2
Отправлено как ответ на запрос участника.
Одна из больших идей Smalltalk - ортогональность. Честно говоря, Python страдает в этом отношении. Не все работает на все. Примеры:
-
inspect.getargspec()
не работает со встроенными функциями или результатами вызововfunctools.partial
(в любом случае интерпретатором C). -
eval
работает только для строк выражений, аexec
работает только для строк операторов. - Лямбда-выражения не могут быть маринованными.
-
myclass = type('x', (object,), {'__init__': partial(foo, value)})
создает класс, который не может быть создан, тогда как передача эквивалентного выраженияlambda
вместоpartial
отлично работает. (Хотя это может быть просто ошибкой, а не особенностью.)
Возможно, PyPy не имеет этих проблем, я не уверен. Но я очень люблю Python и считаю очень удобным использование метаклассов, currying и случайного дескриптора в реальных приложениях.